DEFINE(AOFF_thread_fork_kpsr,
offsetof(struct thread_struct, fork_kpsr));
BLANK();
- DEFINE(AOFF_thread_w_saved, offsetof(struct thread_struct, w_saved));
- DEFINE(AOFF_thread_rwbuf_stkptrs,
- offsetof(struct thread_struct, rwbuf_stkptrs));
- DEFINE(AOFF_thread_reg_window,
- offsetof(struct thread_struct, reg_window));
- BLANK();
DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context));
/* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */
wr %o5, 0x0, %psr ! re-enable interrupts
WRITE_PAUSE ! burn baby burn
3:
- ld [%g6 + TI_TASK], %o4
retl ! return
- st %g0, [%o4 + AOFF_task_thread + AOFF_thread_w_saved] ! no windows saved
+ st %g0, [%g6 + TI_W_SAVED] ! no windows saved
.align 4
.globl C_LABEL(restore_current)
#include <asm/page.h>
#include <asm/psr.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
#include <asm/winmacro.h>
#include <asm/asmmacro.h>
#include <asm/thread_info.h>
*
* sethi %hi(trap_setup), %l4
* jmpl %l4 + %lo(trap_setup), %l6
- * mov 1, %l4
+ * nop
*/
/* 2 3 4 window number
and %t_kstack, %curptr, %curptr
#endif
- /* Clear current->thread.w_saved */
- ld [%curptr + TI_TASK], %g2
- st %g0, [%g2 + AOFF_task_thread + AOFF_thread_w_saved]
+ /* Clear current_thread_info->w_saved */
+ st %g0, [%curptr + TI_W_SAVED]
/* See if we are in the trap window. */
andcc %t_twinmask, %t_wim, %g0
/* From user/kernel into invalid window w/bad user
* stack. Save bad user stack, and return to caller.
*/
- ld [%curptr + TI_TASK], %glob_tmp
- SAVE_BOLIXED_USER_STACK(glob_tmp, g3)
+ SAVE_BOLIXED_USER_STACK(curptr, g3)
restore %g0, %g0, %g0
jmpl %t_retpc + 0x8, %g0
void flush_thread(void)
{
- current->thread.w_saved = 0;
+ current_thread_info()->w_saved = 0;
/* No new signal delivery by default */
current->thread.new_signal = 0;
ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
ti->kwim = current->thread.fork_kwim;
- /* This is used for sun4c only */
- atomic_set(&p->thread.refcount, 1);
-
if(regs->psr & PSR_PS) {
extern struct pt_regs fake_swapper_regs;
struct task_struct *tsk, long *addr)
{
struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_struct *t = &tsk->thread;
+ struct thread_info *t = tsk->thread_info;
int v;
if(offset >= 1024)
}
switch(offset) {
case 0:
- v = tsk->thread_info->ksp;
+ v = t->ksp;
break;
case 4:
- v = tsk->thread_info->kpc;
+ v = t->kpc;
break;
case 8:
- v = tsk->thread_info->kpsr;
+ v = t->kpsr;
break;
case 12:
- v = tsk->thread_info->uwinmask;
+ v = t->uwinmask;
break;
case 832:
v = t->w_saved;
struct task_struct *tsk)
{
struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_struct *t = &tsk->thread;
+ struct thread_info *t = tsk->thread_info;
unsigned long value = regs->u_regs[UREG_I3];
if(offset >= 1024)
#include <asm/cprefix.h>
#include <asm/page.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/asi.h>
#include <asm/smp.h>
wr %t_psr, 0x0, %psr
WRITE_PAUSE
- ld [%curptr + TI_TASK], %o5
- ld [%o5 + AOFF_task_thread + AOFF_thread_w_saved], %twin_tmp1
+ ld [%curptr + TI_W_SAVED], %twin_tmp1
orcc %g0, %twin_tmp1, %g0
be ret_trap_nobufwins
nop
int window = 0, err;
unsigned long pc = regs->pc;
unsigned long npc = regs->npc;
+ struct thread_info *tp = current_thread_info();
void *sig_address;
int sig_code;
err |= __put_user(regs->psr, &sc->sigc_psr);
err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
- err |= __put_user(current->thread.w_saved, &sc->sigc_oswins);
- if (current->thread.w_saved)
- for (window = 0; window < current->thread.w_saved; window++) {
- put_user((char *)current->thread.rwbuf_stkptrs[window],
+ err |= __put_user(tp->w_saved, &sc->sigc_oswins);
+ if (tp->w_saved)
+ for (window = 0; window < tp->w_saved; window++) {
+ put_user((char *)tp->rwbuf_stkptrs[window],
&sc->sigc_spbuf[window]);
err |= __copy_to_user(&sc->sigc_wbuf[window],
- ¤t->thread.reg_window[window],
+ &tp->reg_window[window],
sizeof(struct reg_window));
}
else
err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP],
sizeof(struct reg_window));
- current->thread.w_saved = 0; /* So process is allowed to execute. */
+ tp->w_saved = 0; /* So process is allowed to execute. */
err |= __put_user(signr, &sframep->sig_num);
sig_address = NULL;
if (invalid_frame_pointer(sf, sigframe_size))
goto sigill_and_return;
- if (current->thread.w_saved != 0)
+ if (current_thread_info()->w_saved != 0)
goto sigill_and_return;
/* 2. Save the current process state */
get_sigframe(&ka->sa, regs, sigframe_size);
if (invalid_frame_pointer(sf, sigframe_size))
goto sigill;
- if (current->thread.w_saved != 0)
+ if (current_thread_info()->w_saved != 0)
goto sigill;
err = __put_user(regs->pc, &sf->regs.pc);
svr4_gwindows_t __user *gw;
svr4_ucontext_t __user *uc;
svr4_sigset_t setv;
+ struct thread_info *tp = current_thread_info();
int window = 0, err;
synchronize_user_stack();
err |= __put_user(gw, &mc->gwin);
/* 2. Number of windows to restore at setcontext(): */
- err |= __put_user(current->thread.w_saved, &gw->count);
+ err |= __put_user(tp->w_saved, &gw->count);
/* 3. Save each valid window
* Currently, it makes a copy of the windows from the kernel copy.
* These windows are just used in case synchronize_user_stack failed
* to flush the user windows.
*/
- for (window = 0; window < current->thread.w_saved; window++) {
+ for (window = 0; window < tp->w_saved; window++) {
err |= __put_user((int *) &(gw->win[window]), &gw->winptr[window]);
err |= __copy_to_user(&gw->win[window],
- ¤t->thread.reg_window[window],
+ &tp->reg_window[window],
sizeof(svr4_rwindow_t));
err |= __put_user(0, gw->winptr[window]);
}
/* 4. We just pay attention to the gw->count field on setcontext */
- current->thread.w_saved = 0; /* So process is allowed to execute. */
+ tp->w_saved = 0; /* So process is allowed to execute. */
/* Setup the signal information. Solaris expects a bunch of
* information to be passed to the signal handler, we don't provide
synchronize_user_stack();
- if (current->thread.w_saved)
+ if (current_thread_info()->w_saved)
goto sigsegv_and_return;
err = clear_user(uc, sizeof(*uc));
/* Set the context for a svr4 application, this is Solaris way to sigreturn */
asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
{
- struct thread_struct *tp = ¤t->thread;
svr4_gregset_t __user *gr;
unsigned long pc, npc, psr;
sigset_t set;
* svr4_setup_frame when sync_user_windows is done?
*/
flush_user_windows();
-
- if (tp->w_saved)
+
+ if (current_thread_info()->w_saved)
goto sigsegv_and_return;
if (((uint) c) & 3)
TI_KSP != offsetof(struct thread_info, ksp) ||
TI_KPC != offsetof(struct thread_info, kpc) ||
TI_KPSR != offsetof(struct thread_info, kpsr) ||
- TI_KWIM != offsetof(struct thread_info, kwim))
+ TI_KWIM != offsetof(struct thread_info, kwim) ||
+ TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
+ TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
+ TI_W_SAVED != offsetof(struct thread_info, w_saved))
thread_info_offsets_are_bolixed_pete();
/* Attach to the address space of init_task. */
: "g4", "cc");
}
-static inline void shift_window_buffer(int first_win, int last_win, struct thread_struct *tp)
+static inline void shift_window_buffer(int first_win, int last_win, struct thread_info *tp)
{
int i;
*/
void synchronize_user_stack(void)
{
- struct thread_struct *tp;
+ struct thread_info *tp = current_thread_info();
int window;
flush_user_windows();
- tp = ¤t->thread;
if(!tp->w_saved)
return;
void try_to_clear_window_buffer(struct pt_regs *regs, int who)
{
- struct thread_struct *tp;
+ struct thread_info *tp = current_thread_info();
int window;
lock_kernel();
flush_user_windows();
- tp = ¤t->thread;
for(window = 0; window < tp->w_saved; window++) {
unsigned long sp = tp->rwbuf_stkptrs[window];
#include <asm/contregs.h>
#include <asm/page.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/smp.h>
#include <asm/asi.h>
bne spwin_bad_ustack_from_kernel
nop
- ld [%curptr + TI_TASK], %glob_tmp
-
/* Oh well, throw this one window into the per-task window
* buffer, the first one.
*/
- st %sp, [%glob_tmp + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
- STORE_WINDOW(glob_tmp + AOFF_task_thread + AOFF_thread_reg_window)
+ st %sp, [%curptr + TI_RWIN_SPTRS]
+ STORE_WINDOW(curptr + TI_REG_WINDOW)
restore %g0, %g0, %g0
/* LOCATION: Trap Window */
/* Back in the trap window, update winbuffer save count. */
mov 1, %twin_tmp
- st %twin_tmp, [%glob_tmp + AOFF_task_thread + AOFF_thread_w_saved]
+ st %twin_tmp, [%curptr + TI_W_SAVED]
/* Compute new user window mask. What we are basically
* doing is taking two windows, the invalid one at trap
* a per-process window buffer until we can properly handle
* this later on.
*/
- ld [%curptr + TI_TASK], %glob_tmp /* Using curptr one last time */
- SAVE_BOLIXED_USER_STACK(glob_tmp, g6) /* ...now using g6 as scratch */
+ SAVE_BOLIXED_USER_STACK(curptr, glob_tmp)
restore %g0, %g0, %g0
/* LOCATION: Trap window */
#include <asm/contregs.h>
#include <asm/page.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
#include <asm/psr.h>
#include <asm/smp.h>
#include <asm/asi.h>
mov 0x1, %g5
sll %g5, %g3, %g5
st %g5, [%curptr + TI_UWINMASK] ! one live user window still
- ld [%curptr + TI_TASK], %g5
- st %g0, [%g5 + AOFF_task_thread + AOFF_thread_w_saved] ! no windows in the buffer
+ st %g0, [%curptr + TI_W_SAVED] ! no windows in the buffer
wr %t_psr, PSR_ET, %psr ! enable traps
nop
{
unsigned long sp;
- sp = current->thread.rwbuf_stkptrs[0];
+ sp = current_thread_info()->rwbuf_stkptrs[0];
if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
force_user_fault(sp + 0x38, 1);
force_user_fault(sp, 1);
if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) {
highstart_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT);
max_low_pfn = calc_max_low_pfn();
- printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", calc_highpages());
+ printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ calc_highpages() >> (20 - PAGE_SHIFT));
}
#ifdef CONFIG_BLK_DEV_INITRD
unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tiaddr));
int entry = BUCKET_NUM(tiaddr);
- if (atomic_dec_and_test(&ti->task->thread.refcount)) {
- /* We are deleting a mapping, so the flush here is mandatory. */
- sun4c_flush_page(tiaddr);
+ /* We are deleting a mapping, so the flush here is mandatory. */
+ sun4c_flush_page(tiaddr);
#ifndef CONFIG_SUN4
- sun4c_flush_page(tiaddr + PAGE_SIZE);
+ sun4c_flush_page(tiaddr + PAGE_SIZE);
#endif
- sun4c_put_pte(tiaddr, 0);
+ sun4c_put_pte(tiaddr, 0);
#ifndef CONFIG_SUN4
- sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
+ sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
#endif
- sun4c_bucket[entry] = BUCKET_EMPTY;
- if (entry < sun4c_lowbucket_avail)
- sun4c_lowbucket_avail = entry;
+ sun4c_bucket[entry] = BUCKET_EMPTY;
+ if (entry < sun4c_lowbucket_avail)
+ sun4c_lowbucket_avail = entry;
- free_pages(pages, THREAD_INFO_ORDER);
- garbage_collect(entry);
- }
+ free_pages(pages, THREAD_INFO_ORDER);
+ garbage_collect(entry);
}
static void __init sun4c_init_buckets(void)
/* The Sparc processor specific thread struct. */
struct thread_struct {
struct pt_regs *kregs;
+ unsigned int _pad1;
/* Special child fork kpsr/kwim values. */
unsigned long fork_kpsr __attribute__ ((aligned (8)));
unsigned long fork_kwim;
- /* A place to store user windows and stack pointers
- * when the stack needs inspection.
- */
-#define NSWINS 8
- struct reg_window reg_window[NSWINS] __attribute__ ((aligned (8)));
- unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
- unsigned long w_saved;
-
/* Floating point regs */
unsigned long float_regs[32] __attribute__ ((aligned (8)));
unsigned long fsr;
mm_segment_t current_ds;
struct exec core_exec; /* just what it says. */
int new_signal;
- atomic_t refcount; /* used for sun4c only */
};
#define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */
#define SPARC_FLAG_UNALIGNED 0x2 /* is allowed to do unaligned accesses */
#define INIT_THREAD { \
-/* kregs, */ \
- 0, \
+/* kregs, _pad1, */ \
+ 0, 0, \
/* fork_kpsr, fork_kwim */ \
0, 0, \
-/* reg_window */ \
-{ { { 0, }, { 0, } }, }, \
-/* rwbuf_stkptrs */ \
-{ 0, 0, 0, 0, 0, 0, 0, 0, }, \
-/* w_saved */ \
- 0, \
/* FPU regs */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
/* FPU status, FPU qdepth, FPU queue */ \
#ifndef __ASSEMBLY__
#include <asm/btfixup.h>
+#include <asm/ptrace.h>
/*
* Low level task data.
*
- * If you change this, change the TI_* offsets below to match. XXX check_asm.
- *
- * The uwinmask is a first class citizen among w_saved and friends.
- * XXX Is this a good idea? wof.S/wuf.S have to use w_saved anyway,
- * so they waste a register on current, and an ld on fetching it.
+ * If you change this, change the TI_* offsets below to match.
*/
+#define NSWINS 8
struct thread_info {
unsigned long uwinmask;
struct task_struct *task; /* main task structure */
unsigned long kpsr;
unsigned long kwim;
+ /* A place to store user windows and stack pointers
+ * when the stack needs inspection.
+ */
+ struct reg_window reg_window[NSWINS]; /* align for ldd! */
+ unsigned long rwbuf_stkptrs[NSWINS];
+ unsigned long w_saved;
+
struct restart_block restart_block;
};
/*
* Offsets in thread_info structure, used in assembly code
+ * The "#define REGWIN_SZ 0x40" was abolished, so no multiplications.
*/
#define TI_UWINMASK 0x00 /* uwinmask */
#define TI_TASK 0x04
#define TI_KPC 0x24 /* kpc (ldd'ed with kpc) */
#define TI_KPSR 0x28 /* kpsr */
#define TI_KWIM 0x2c /* kwim (ldd'ed with kpsr) */
-#define TI_RESTART_BLOCK 0x30
+#define TI_REG_WINDOW 0x30
+#define TI_RWIN_SPTRS 0x230
+#define TI_W_SAVED 0x250
+/* #define TI_RESTART_BLOCK 0x25n */ /* Nobody cares */
#define PREEMPT_ACTIVE 0x4000000
#include <linux/config.h>
#include <asm/ptrace.h>
-#include <asm/psr.h>
/* Store the register window onto the 8-byte aligned area starting
* at %reg. It might be %sp, it might not, we don't care.
STORE_PT_INS(base_reg)
#define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \
- ld [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved], %scratch; \
+ ld [%cur_reg + TI_W_SAVED], %scratch; \
sll %scratch, 2, %scratch; \
add %scratch, %cur_reg, %scratch; \
- st %sp, [%scratch + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]; \
+ st %sp, [%scratch + TI_RWIN_SPTRS]; \
sub %scratch, %cur_reg, %scratch; \
sll %scratch, 4, %scratch; \
add %scratch, %cur_reg, %scratch; \
- STORE_WINDOW(scratch + AOFF_task_thread + AOFF_thread_reg_window); \
+ STORE_WINDOW(scratch + TI_REG_WINDOW); \
sub %scratch, %cur_reg, %scratch; \
srl %scratch, 6, %scratch; \
add %scratch, 1, %scratch; \
- st %scratch, [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved];
+ st %scratch, [%cur_reg + TI_W_SAVED];
#ifdef CONFIG_SMP
#define LOAD_CURRENT4M(dest_reg, idreg) \