Commit e18fad25 authored by Linus Torvalds's avatar Linus Torvalds

Merge

parents 77ae7b5e 8a3fb763
...@@ -117,11 +117,13 @@ srmboot: ...@@ -117,11 +117,13 @@ srmboot:
archclean: archclean:
@$(MAKE) -C arch/alpha/kernel clean @$(MAKE) -C arch/alpha/kernel clean
@$(MAKEBOOT) clean @$(MAKEBOOT) clean
rm -f arch/alpha/vmlinux.lds
archmrproper: archmrproper:
rm -f arch/alpha/vmlinux.lds
rm -f include/asm-alpha/asm_offsets.h
archdep: archdep:
$(MAKE) -C arch/alpha/kernel asm_offsets
@$(MAKEBOOT) dep @$(MAKEBOOT) dep
vmlinux: arch/alpha/vmlinux.lds vmlinux: arch/alpha/vmlinux.lds
......
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
# Note 2! The CFLAGS definitions are now in the main makefile... # Note 2! The CFLAGS definitions are now in the main makefile...
.S.s: .S.s:
$(CPP) $(AFLAGS) -o $*.s $< $(CPP) $(CFLAGS) $(AFLAGS) -o $*.s $<
.S.o: .S.o:
$(CC) $(AFLAGS) -c -o $*.o $< $(CC) $(CFLAGS) $(AFLAGS) -c -o $*.o $<
O_TARGET := kernel.o O_TARGET := kernel.o
export-objs := alpha_ksyms.o export-objs := alpha_ksyms.o
obj-y := entry.o traps.o process.o osf_sys.o irq.o irq_alpha.o \ obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o irq_alpha.o \
signal.o setup.o ptrace.o time.o semaphore.o alpha_ksyms.o signal.o setup.o ptrace.o time.o semaphore.o alpha_ksyms.o
# #
...@@ -102,11 +102,15 @@ endif # GENERIC ...@@ -102,11 +102,15 @@ endif # GENERIC
all: kernel.o head.o all: kernel.o head.o
asm_offsets: check_asm ASM_OFFSETS_H = $(TOPDIR)/include/asm-alpha/asm_offsets.h
./check_asm > $(TOPDIR)/include/asm-alpha/asm_offsets.h asm_offsets:
$(CC) $(CFLAGS) -S -o - check_asm.c | \
check_asm: check_asm.c sed -e '/xyzzy/ { s/xyzzy //; p; }; d;' > asm_offsets.tmp
$(HOSTCC) -o $@ $< $(CPPFLAGS) -ffixed-8 @if cmp -s asm_offsets.tmp $(ASM_OFFSETS_H); then \
set -x; rm asm_offsets.tmp; \
else \
set -x; mv asm_offsets.tmp $(ASM_OFFSETS_H); \
fi
clean:: clean::
rm -f check_asm rm -f check_asm
......
...@@ -3,30 +3,28 @@ ...@@ -3,30 +3,28 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/io.h> #include <asm/io.h>
int main() #define OUT(x) \
asm ("\nxyzzy " x)
#define DEF(name, val) \
asm volatile ("\nxyzzy #define " name " %0" : : "i"(val))
void foo(void)
{ {
printf("#ifndef __ASM_OFFSETS_H__\n#define __ASM_OFFSETS_H__\n"); OUT("#ifndef __ASM_OFFSETS_H__");
OUT("#define __ASM_OFFSETS_H__");
OUT("");
DEF("TI_TASK", offsetof(struct thread_info, task));
DEF("TI_FLAGS", offsetof(struct thread_info, flags));
DEF("TI_CPU", offsetof(struct thread_info, cpu));
printf("#define TASK_STATE %ld\n", DEF("PT_PTRACED", PT_PTRACED);
(long)offsetof(struct task_struct, state)); DEF("CLONE_VM", CLONE_VM);
printf("#define TASK_FLAGS %ld\n", DEF("SIGCHLD", SIGCHLD);
(long)offsetof(struct task_struct, flags));
printf("#define TASK_SIGPENDING %ld\n",
#error (long)offsetof(struct task_struct, sigpending));
printf("#define TASK_ADDR_LIMIT %ld\n",
(long)offsetof(struct task_struct, addr_limit));
printf("#define TASK_EXEC_DOMAIN %ld\n",
(long)offsetof(struct task_struct, exec_domain));
printf("#define TASK_NEED_RESCHED %ld\n",
#error (long)offsetof(struct task_struct, work.need_resched));
printf("#define TASK_SIZE %ld\n", sizeof(struct task_struct));
printf("#define STACK_SIZE %ld\n", sizeof(union task_union));
printf("#define HAE_CACHE %ld\n", DEF("HAE_CACHE", offsetof(struct alpha_machine_vector, hae_cache));
(long)offsetof(struct alpha_machine_vector, hae_cache)); DEF("HAE_REG", offsetof(struct alpha_machine_vector, hae_register));
printf("#define HAE_REG %ld\n",
(long)offsetof(struct alpha_machine_vector, hae_register));
printf("#endif /* __ASM_OFFSETS_H__ */\n"); OUT("");
return 0; OUT("#endif /* __ASM_OFFSETS_H__ */");
} }
...@@ -7,42 +7,16 @@ ...@@ -7,42 +7,16 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/asm_offsets.h>
#include <asm/thread_info.h>
#define SIGCHLD 20 #define NR_SYSCALLS 381
#define NR_SYSCALLS 378
/*
* These offsets must match with alpha_mv in <asm/machvec.h>.
*/
#define HAE_CACHE 0
#define HAE_REG 8
/* /*
* stack offsets * stack offsets
*/ */
#define SP_OFF 184 #define SP_OFF 184
#define SWITCH_STACK_SIZE 320
#define SWITCH_STACK_SIZE 320
/*
* task structure offsets
*/
#define TASK_STATE 0
#define TASK_FLAGS 8
#error #define TASK_SIGPENDING 16
#define TASK_ADDR_LIMIT 24
#define TASK_EXEC_DOMAIN 32
#error #define TASK_NEED_RESCHED 40
#error #define TASK_PTRACE 48
#define TASK_PROCESSOR 100
/*
* task flags (must match include/linux/sched.h):
*/
#define PT_PTRACED 0x00000001
#define CLONE_VM 0x00000100
/* /*
* This defines the normal kernel pt-regs layout. * This defines the normal kernel pt-regs layout.
...@@ -55,7 +29,7 @@ ...@@ -55,7 +29,7 @@
*/ */
#define SAVE_ALL \ #define SAVE_ALL \
subq $30,184,$30; \ subq $30,SP_OFF,$30; \
stq $0,0($30); \ stq $0,0($30); \
stq $1,8($30); \ stq $1,8($30); \
stq $2,16($30); \ stq $2,16($30); \
...@@ -98,12 +72,8 @@ ...@@ -98,12 +72,8 @@
ldq $8,64($30); \ ldq $8,64($30); \
beq $20,99f; \ beq $20,99f; \
ldq $20,HAE_REG($19); \ ldq $20,HAE_REG($19); \
addq $31,7,$16; \
call_pal PAL_swpipl; \
stq $21,HAE_CACHE($19); \ stq $21,HAE_CACHE($19); \
stq $21,0($20); \ stq $21,0($20); \
mov $0,$16; \
call_pal PAL_swpipl; \
ldq $0,0($30); \ ldq $0,0($30); \
ldq $1,8($30); \ ldq $1,8($30); \
99:; \ 99:; \
...@@ -117,13 +87,10 @@ ...@@ -117,13 +87,10 @@
ldq $26,128($30); \ ldq $26,128($30); \
ldq $27,136($30); \ ldq $27,136($30); \
ldq $28,144($30); \ ldq $28,144($30); \
addq $30,184,$30 addq $30,SP_OFF,$30
.text .text
.set noat .set noat
#if defined(__linux__) && !defined(__ELF__)
.set singlegp
#endif
.align 3 .align 3
.globl entInt .globl entInt
...@@ -202,69 +169,58 @@ entDbg: ...@@ -202,69 +169,58 @@ entDbg:
.end entDbg .end entDbg
/*
* Fork() is one of the special system calls: it needs to
* save the callee-saved regs so that the regs can be found
* for the new process.. We save them in the "context switch"
* stack format (see arch/alpha/kernel/process.c).
*
* Also, for the kernel fork, we need to fake the system call
* stack buildup, as we can't do system calls from kernel space.
*/
.align 3
.ent kernel_clone
kernel_clone:
.frame $30, 0, $26
.prologue 0
subq $30,6*8,$30
stq $31,0($30)
stq $26,8($30)
stq $29,16($30)
stq $16,24($30)
stq $17,32($30)
stq $18,40($30)
bis $31,2,$0 /* Register v0: syscall nr for fork() */
SAVE_ALL
bsr $26,sys_clone
stq $0,0($30)
br ret_from_sys_call
.end kernel_clone
/* /*
* kernel_thread(fn, arg, clone_flags) * kernel_thread(fn, arg, clone_flags)
*/ */
.align 3 .align 4
.globl kernel_thread .globl kernel_thread
.ent kernel_thread .ent kernel_thread
kernel_thread: kernel_thread:
ldgp $29,0($27) /* we can be called from a module */ ldgp $29,0($27) /* we can be called from a module */
.frame $30, 4*8, $26
subq $30,4*8,$30
stq $10,16($30)
stq $9,8($30)
lda $0,CLONE_VM
stq $26,0($30)
.prologue 1 .prologue 1
mov $16,$9 /* save fn */ subq $30,SP_OFF+6*8,$30
mov $17,$10 /* save arg */ br $1, 2f /* load start address */
or $18,$0,$16 /* shuffle flags to front; add CLONE_VM. */
bsr $26,kernel_clone /* We've now "returned" from a fake system call. */
bne $20,1f /* $20 is non-zero in child */ unop
ldq $26,0($30) blt $0, 1f /* error? */
ldq $9,8($30) ldi $1, 0x3fff
ldq $10,16($30) beq $20, 1f /* parent or child? */
addq $30,4*8,$30
ret $31,($26),1 bic $30, $1, $8 /* in child. */
/* this is in child: look out as we don't have any stack here.. */ jsr $26, ($27)
1: mov $9,$27 /* get fn */ ldgp $29, 0($26)
lda $8,0x3fff mov $0, $16
mov $10,$16 /* get arg */ mov $31, $26
bic $30,$8,$8 /* get current */ jmp $31, sys_exit
jsr $26,($27)
ldgp $29,0($26) 1: ret /* in parent. */
mov $0,$16
mov $31,$26 .align 4
jsr $31,sys_exit 2: /* Fake a system call stack frame, as we can't do system calls
from kernel space. Note that we store FN and ARG as they
need to be set up in the child for the call. Also store $8
and $26 for use in the parent. */
stq $31, SP_OFF($30) /* ps */
stq $1, SP_OFF+8($30) /* pc */
stq $29, SP_OFF+16($30) /* gp */
stq $16, 136($30) /* $27; FN for child */
stq $17, SP_OFF+24($30) /* $16; ARG for child */
stq $8, 64($30) /* $8 */
stq $26, 128($30) /* $26 */
/* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
ldq $2, alpha_mv+HAE_CACHE
stq $2, 152($30) /* HAE */
/* Shuffle FLAGS to the front; add CLONE_VM. */
ldi $1, CLONE_VM
or $18, $1, $16
bsr $26, sys_clone
/* We don't actually care for a3 success widgetry in the kernel.
Not for positive errno values. */
stq $0, 0($30) /* $0 */
br restore_all
.end kernel_thread .end kernel_thread
/* /*
...@@ -535,10 +491,21 @@ alpha_switch_to: ...@@ -535,10 +491,21 @@ alpha_switch_to:
call_pal PAL_swpctx call_pal PAL_swpctx
unop unop
bsr $1,undo_switch_stack bsr $1,undo_switch_stack
lda $8,0x3fff
mov $17,$0 mov $17,$0
bic $30,$8,$8
ret $31,($26),1 ret $31,($26),1
.end alpha_switch_to .end alpha_switch_to
.globl ret_from_fork
.align 3
.ent ret_from_fork
ret_from_fork:
lda $26,ret_from_sys_call
mov $0,$16
jmp $31,schedule_tail
.end ret_from_fork
/* /*
* Oh, well.. Disassembling OSF/1 binaries to find out how the * Oh, well.. Disassembling OSF/1 binaries to find out how the
* system calls work isn't much fun. * system calls work isn't much fun.
...@@ -559,12 +526,11 @@ entSys: ...@@ -559,12 +526,11 @@ entSys:
lda $5,sys_call_table lda $5,sys_call_table
lda $27,sys_ni_syscall lda $27,sys_ni_syscall
cmpult $0,$4,$4 cmpult $0,$4,$4
ldq $3,TASK_PTRACE($8) ldl $3,TI_FLAGS($8)
stq $17,SP_OFF+32($30) stq $17,SP_OFF+32($30)
s8addq $0,$5,$5 s8addq $0,$5,$5
and $3,PT_PTRACED,$3
stq $18,SP_OFF+40($30) stq $18,SP_OFF+40($30)
bne $3,strace blbs $3,strace
beq $4,1f beq $4,1f
ldq $27,0($5) ldq $27,0($5)
1: jsr $26,($27),alpha_ni_syscall 1: jsr $26,($27),alpha_ni_syscall
...@@ -580,34 +546,65 @@ ret_from_sys_call: ...@@ -580,34 +546,65 @@ ret_from_sys_call:
and $0,8,$0 and $0,8,$0
beq $0,restore_all beq $0,restore_all
ret_from_reschedule: ret_from_reschedule:
#error ldq $2,TASK_NEED_RESCHED($8) /* Make sure need_resched and sigpending don't change between
lda $4,init_task_union sampling and the rti. */
bne $2,reschedule lda $16,7
xor $4,$8,$4 call_pal PAL_swpipl
#error ldl $5,TASK_SIGPENDING($8) ldl $5,TI_FLAGS($8)
beq $4,restore_all and $5,_TIF_WORK_MASK,$2
bne $5,signal_return bne $5,work_pending
restore_all: restore_all:
RESTORE_ALL RESTORE_ALL
call_pal PAL_rti call_pal PAL_rti
work_pending:
and $5,_TIF_NEED_RESCHED,$2
beq $2,work_notifysig
work_resched:
subq $30,16,$30
stq $19,0($30) /* save syscall nr */
stq $20,8($30) /* and error indication (a3) */
jsr $26,schedule
ldq $19,0($30)
ldq $20,8($30)
addq $30,16,$30
/* Make sure need_resched and sigpending don't change between
sampling and the rti. */
lda $16,7
call_pal PAL_swpipl
ldl $5,TI_FLAGS($8)
and $5,_TIF_WORK_MASK,$2
beq $2,restore_all
and $5,_TIF_NEED_RESCHED,$2
bne $2,work_resched
work_notifysig:
mov $30,$17
br $1,do_switch_stack
mov $5,$21
mov $30,$18
mov $31,$16
jsr $26,do_notify_resume
bsr $1,undo_switch_stack
br restore_all
/* PTRACE syscall handler */ /* PTRACE syscall handler */
.align 3 .align 3
strace: strace:
/* set up signal stack, call syscall_trace */ /* set up signal stack, call syscall_trace */
bsr $1,do_switch_stack bsr $1,do_switch_stack
jsr $26,syscall_trace jsr $26,syscall_trace
bsr $1,undo_switch_stack bsr $1,undo_switch_stack
/* get the system call number and the arguments back.. */ /* get the system call number and the arguments back.. */
ldq $0,0($30) ldq $0,0($30)
ldq $16,SP_OFF+24($30) ldq $16,SP_OFF+24($30)
ldq $17,SP_OFF+32($30) ldq $17,SP_OFF+32($30)
ldq $18,SP_OFF+40($30) ldq $18,SP_OFF+40($30)
ldq $19,72($30) ldq $19,72($30)
ldq $20,80($30) ldq $20,80($30)
ldq $21,88($30) ldq $21,88($30)
/* get the system call pointer.. */ /* get the system call pointer.. */
lda $1,NR_SYSCALLS($31) lda $1,NR_SYSCALLS($31)
...@@ -627,11 +624,11 @@ strace_success: ...@@ -627,11 +624,11 @@ strace_success:
stq $0,0($30) /* save return value */ stq $0,0($30) /* save return value */
bsr $1,do_switch_stack bsr $1,do_switch_stack
jsr $26,syscall_trace jsr $26,syscall_trace
bsr $1,undo_switch_stack bsr $1,undo_switch_stack
br $31,ret_from_sys_call br $31,ret_from_sys_call
.align 3 .align 3
strace_error: strace_error:
ldq $19,0($30) /* old syscall nr (zero if success) */ ldq $19,0($30) /* old syscall nr (zero if success) */
beq $19,strace_success beq $19,strace_success
...@@ -645,7 +642,7 @@ strace_error: ...@@ -645,7 +642,7 @@ strace_error:
bsr $1,do_switch_stack bsr $1,do_switch_stack
mov $19,$9 /* save old syscall number */ mov $19,$9 /* save old syscall number */
mov $20,$10 /* save old a3 */ mov $20,$10 /* save old a3 */
jsr $26,syscall_trace jsr $26,syscall_trace
mov $9,$19 mov $9,$19
mov $10,$20 mov $10,$20
bsr $1,undo_switch_stack bsr $1,undo_switch_stack
...@@ -677,40 +674,8 @@ ret_success: ...@@ -677,40 +674,8 @@ ret_success:
stq $0,0($30) stq $0,0($30)
stq $31,72($30) /* a3=0 => no error */ stq $31,72($30) /* a3=0 => no error */
br ret_from_sys_call br ret_from_sys_call
.align 3
signal_return:
mov $30,$17
br $1,do_switch_stack
mov $30,$18
mov $31,$16
jsr $26,do_signal
bsr $1,undo_switch_stack
br restore_all
.end entSys .end entSys
.globl ret_from_fork
.align 3
.ent ret_from_fork
ret_from_fork:
lda $26,ret_from_sys_call
mov $17,$16
jsr $31,schedule_tail
.end ret_from_fork
.align 3
.ent reschedule
reschedule:
subq $30,16,$30
stq $19,0($30) /* save syscall nr */
stq $20,8($30) /* and error indication (a3) */
jsr $26,schedule
ldq $19,0($30)
ldq $20,8($30)
addq $30,16,$30
br ret_from_reschedule
.end reschedule
.align 3 .align 3
.ent sys_sigreturn .ent sys_sigreturn
sys_sigreturn: sys_sigreturn:
......
...@@ -22,8 +22,8 @@ __start: ...@@ -22,8 +22,8 @@ __start:
.prologue 0 .prologue 0
br $27,1f br $27,1f
1: ldgp $29,0($27) 1: ldgp $29,0($27)
/* We need to get current loaded up with our first task... */ /* We need to get current_task_info loaded up... */
lda $8,init_task_union lda $8,init_thread_union
/* ... and find our stack ... */ /* ... and find our stack ... */
lda $30,0x4000($8) lda $30,0x4000($8)
/* ... and then we can start the kernel. */ /* ... and then we can start the kernel. */
......
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
struct task_struct init_task = INIT_TASK(init_task);
union thread_union init_thread_union
__attribute__((section(".data.init_thread")))
= { INIT_THREAD_INFO(init_task) };
...@@ -776,7 +776,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, ...@@ -776,7 +776,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
/* Return current software fp control & status bits. */ /* Return current software fp control & status bits. */
/* Note that DU doesn't verify available space here. */ /* Note that DU doesn't verify available space here. */
w = current->thread.flags & IEEE_SW_MASK; w = current_thread_info()->ieee_state & IEEE_SW_MASK;
w = swcr_update_status(w, rdfpcr()); w = swcr_update_status(w, rdfpcr());
if (put_user(w, (unsigned long *) buffer)) if (put_user(w, (unsigned long *) buffer))
return -EFAULT; return -EFAULT;
...@@ -793,7 +793,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, ...@@ -793,7 +793,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
case GSI_UACPROC: case GSI_UACPROC:
if (nbytes < sizeof(unsigned int)) if (nbytes < sizeof(unsigned int))
return -EINVAL; return -EINVAL;
w = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; w = (current_thread_info()->flags >> UAC_SHIFT) & UAC_BITMASK;
if (put_user(w, (unsigned int *)buffer)) if (put_user(w, (unsigned int *)buffer))
return -EFAULT; return -EFAULT;
return 1; return 1;
...@@ -840,8 +840,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, ...@@ -840,8 +840,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
/* Update softare trap enable bits. */ /* Update softare trap enable bits. */
if (get_user(swcr, (unsigned long *)buffer)) if (get_user(swcr, (unsigned long *)buffer))
return -EFAULT; return -EFAULT;
current->thread.flags &= ~IEEE_SW_MASK; current_thread_info()->ieee_state
current->thread.flags |= swcr & IEEE_SW_MASK; = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
| (swcr & IEEE_SW_MASK));
/* Update the real fpcr. */ /* Update the real fpcr. */
fpcr = rdfpcr(); fpcr = rdfpcr();
...@@ -869,18 +870,23 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, ...@@ -869,18 +870,23 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
case SSI_NVPAIRS: { case SSI_NVPAIRS: {
unsigned long v, w, i; unsigned long v, w, i;
unsigned int old, new;
for (i = 0; i < nbytes; ++i) { for (i = 0; i < nbytes; ++i) {
if (get_user(v, 2*i + (unsigned int *)buffer)) if (get_user(v, 2*i + (unsigned int *)buffer))
return -EFAULT; return -EFAULT;
if (get_user(w, 2*i + 1 + (unsigned int *)buffer)) if (get_user(w, 2*i + 1 + (unsigned int *)buffer))
return -EFAULT; return -EFAULT;
switch (v) { switch (v) {
case SSIN_UACPROC: case SSIN_UACPROC:
current->thread.flags &= again:
~(UAC_BITMASK << UAC_SHIFT); old = current_thread_info()->flags;
current->thread.flags |= new = old & ~(UAC_BITMASK << UAC_SHIFT);
(w & UAC_BITMASK) << UAC_SHIFT; new = new | (w & UAC_BITMASK) << UAC_SHIFT;
if (cmpxchg(&current_thread_info()->flags,
old, new) != old)
goto again;
break; break;
default: default:
......
...@@ -411,13 +411,8 @@ pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, ...@@ -411,13 +411,8 @@ pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
Write dma_length of each leader with the combined lengths of Write dma_length of each leader with the combined lengths of
the mergable followers. */ the mergable followers. */
#define SG_ENT_VIRT_ADDRESS(SG) \ #define SG_ENT_VIRT_ADDRESS(SG) (page_address((SG)->page) + (SG)->offset)
((SG)->address \ #define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
? (SG)->address \
: page_address((SG)->page) + (SG)->offset)
#define SG_ENT_PHYS_ADDRESS(SG) \
__pa(SG_ENT_VIRT_ADDRESS(SG))
static void static void
sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok) sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
......
...@@ -42,22 +42,6 @@ ...@@ -42,22 +42,6 @@
#include "proto.h" #include "proto.h"
#include "pci_impl.h" #include "pci_impl.h"
/*
* Initial task structure. Make this a per-architecture thing,
* because different architectures tend to have different
* alignment requirements and potentially different initial
* setup.
*/
unsigned long init_user_stack[1024] = { STACK_MAGIC, };
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
union task_union init_task_union __attribute__((section("init_task")))
= { task: INIT_TASK(init_task_union.task) };
/* /*
* No need to acquire the kernel lock, we're entirely local.. * No need to acquire the kernel lock, we're entirely local..
*/ */
...@@ -73,18 +57,12 @@ sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, ...@@ -73,18 +57,12 @@ sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
void void
cpu_idle(void) cpu_idle(void)
{ {
/* An endless idle loop with no priority at all. */
current->nice = 20;
while (1) { while (1) {
/* FIXME -- EV6 and LCA45 know how to power down /* FIXME -- EV6 and LCA45 know how to power down
the CPU. */ the CPU. */
/* Although we are an idle CPU, we do not want to while (!need_resched())
get into the scheduler unnecessarily. */ barrier();
long oldval = xchg(&current->work.need_resched, -1UL);
if (!oldval)
while (current->work.need_resched < 0);
schedule(); schedule();
check_pgt_cache(); check_pgt_cache();
} }
...@@ -152,7 +130,7 @@ common_shutdown_1(void *generic_ptr) ...@@ -152,7 +130,7 @@ common_shutdown_1(void *generic_ptr)
barrier(); barrier();
#endif #endif
/* If booted from SRM, reset some of the original environment. */ /* If booted from SRM, reset some of the original environment. */
if (alpha_using_srm) { if (alpha_using_srm) {
#ifdef CONFIG_DUMMY_CONSOLE #ifdef CONFIG_DUMMY_CONSOLE
/* This has the effect of resetting the VGA video origin. */ /* This has the effect of resetting the VGA video origin. */
...@@ -255,7 +233,7 @@ flush_thread(void) ...@@ -255,7 +233,7 @@ flush_thread(void)
{ {
/* Arrange for each exec'ed process to start off with a clean slate /* Arrange for each exec'ed process to start off with a clean slate
with respect to the FPU. This is all exceptions disabled. */ with respect to the FPU. This is all exceptions disabled. */
current->thread.flags &= ~IEEE_SW_MASK; current_thread_info()->ieee_state = 0;
wrfpcr(FPCR_DYN_NORMAL | ieee_swcr_to_fpcr(0)); wrfpcr(FPCR_DYN_NORMAL | ieee_swcr_to_fpcr(0));
} }
...@@ -294,8 +272,8 @@ alpha_vfork(struct switch_stack * swstack) ...@@ -294,8 +272,8 @@ alpha_vfork(struct switch_stack * swstack)
* *
* Note the "stack_offset" stuff: when returning to kernel mode, we need * Note the "stack_offset" stuff: when returning to kernel mode, we need
* to have some extra stack-space for the kernel stack that still exists * to have some extra stack-space for the kernel stack that still exists
* after the "ret_from_sys_call". When returning to user mode, we only * after the "ret_from_fork". When returning to user mode, we only want
* want the space needed by the syscall stack frame (ie "struct pt_regs"). * the space needed by the syscall stack frame (ie "struct pt_regs").
* Use the passed "regs" pointer to determine how much space we need * Use the passed "regs" pointer to determine how much space we need
* for a kernel fork(). * for a kernel fork().
*/ */
...@@ -305,9 +283,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -305,9 +283,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long unused, unsigned long unused,
struct task_struct * p, struct pt_regs * regs) struct task_struct * p, struct pt_regs * regs)
{ {
extern void ret_from_sys_call(void);
extern void ret_from_fork(void); extern void ret_from_fork(void);
struct thread_info *childti = p->thread_info;
struct pt_regs * childregs; struct pt_regs * childregs;
struct switch_stack * childstack, *stack; struct switch_stack * childstack, *stack;
unsigned long stack_offset; unsigned long stack_offset;
...@@ -315,7 +293,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -315,7 +293,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
stack_offset = PAGE_SIZE - sizeof(struct pt_regs); stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
if (!(regs->ps & 8)) if (!(regs->ps & 8))
stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
childregs = (struct pt_regs *) (stack_offset + PAGE_SIZE + (long)p); childregs = (struct pt_regs *)
(stack_offset + PAGE_SIZE + (long) childti);
*childregs = *regs; *childregs = *regs;
childregs->r0 = 0; childregs->r0 = 0;
...@@ -326,10 +305,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -326,10 +305,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childstack = ((struct switch_stack *) childregs) - 1; childstack = ((struct switch_stack *) childregs) - 1;
*childstack = *stack; *childstack = *stack;
childstack->r26 = (unsigned long) ret_from_fork; childstack->r26 = (unsigned long) ret_from_fork;
p->thread.usp = usp; childti->pcb.usp = usp;
p->thread.ksp = (unsigned long) childstack; childti->pcb.ksp = (unsigned long) childstack;
p->thread.pal_flags = 1; /* set FEN, clear everything else */ childti->pcb.flags = 1; /* set FEN, clear everything else */
p->thread.flags = current->thread.flags;
return 0; return 0;
} }
...@@ -432,6 +410,35 @@ sys_execve(char *ufilename, char **argv, char **envp, ...@@ -432,6 +410,35 @@ sys_execve(char *ufilename, char **argv, char **envp,
return error; return error;
} }
/*
* Return saved PC of a blocked thread. This assumes the frame
* pointer is the 6th saved long on the kernel stack and that the
* saved return address is the first long in the frame. This all
* holds provided the thread blocked through a call to schedule() ($15
* is the frame pointer in schedule() and $15 is saved at offset 48 by
* entry.S:do_switch_stack).
*
* Under heavy swap load I've seen this lose in an ugly way. So do
* some extra sanity checking on the ranges we expect these pointers
* to be in so that we can fail gracefully. This is just for ps after
* all. -- r~
*/
unsigned long
thread_saved_pc(task_t *t)
{
unsigned long base = (unsigned long)t->thread_info;
unsigned long fp, sp = t->thread_info->pcb.ksp;
if (sp > base && sp+6*8 < base + 16*1024) {
fp = ((unsigned long*)sp)[6];
if (fp > sp && fp < base + 16*1024)
return *(unsigned long *)fp;
}
return 0;
}
/* /*
* These bracket the sleeping functions.. * These bracket the sleeping functions..
*/ */
...@@ -457,9 +464,9 @@ get_wchan(struct task_struct *p) ...@@ -457,9 +464,9 @@ get_wchan(struct task_struct *p)
* after all... * after all...
*/ */
pc = thread_saved_pc(&p->thread); pc = thread_saved_pc(p);
if (pc >= first_sched && pc < last_sched) { if (pc >= first_sched && pc < last_sched) {
schedule_frame = ((unsigned long *)p->thread.ksp)[6]; schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
return ((unsigned long *)schedule_frame)[12]; return ((unsigned long *)schedule_frame)[12];
} }
return pc; return pc;
......
...@@ -101,7 +101,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno) ...@@ -101,7 +101,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
long *addr; long *addr;
if (regno == 30) { if (regno == 30) {
addr = &task->thread.usp; addr = &task->thread_info->pcb.usp;
} else if (regno == 31 || regno > 64) { } else if (regno == 31 || regno > 64) {
zero = 0; zero = 0;
addr = &zero; addr = &zero;
...@@ -120,7 +120,8 @@ get_reg(struct task_struct * task, unsigned long regno) ...@@ -120,7 +120,8 @@ get_reg(struct task_struct * task, unsigned long regno)
/* Special hack for fpcr -- combine hardware and software bits. */ /* Special hack for fpcr -- combine hardware and software bits. */
if (regno == 63) { if (regno == 63) {
unsigned long fpcr = *get_reg_addr(task, regno); unsigned long fpcr = *get_reg_addr(task, regno);
unsigned long swcr = task->thread.flags & IEEE_SW_MASK; unsigned long swcr
= task->thread_info->ieee_state & IEEE_SW_MASK;
swcr = swcr_update_status(swcr, fpcr); swcr = swcr_update_status(swcr, fpcr);
return fpcr | swcr; return fpcr | swcr;
} }
...@@ -134,8 +135,9 @@ static int ...@@ -134,8 +135,9 @@ static int
put_reg(struct task_struct *task, unsigned long regno, long data) put_reg(struct task_struct *task, unsigned long regno, long data)
{ {
if (regno == 63) { if (regno == 63) {
task->thread.flags = ((task->thread.flags & ~IEEE_SW_MASK) task->thread_info->ieee_state
| (data & IEEE_SW_MASK)); = ((task->thread_info->ieee_state & ~IEEE_SW_MASK)
| (data & IEEE_SW_MASK));
data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data); data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
} }
*get_reg_addr(task, regno) = data; *get_reg_addr(task, regno) = data;
...@@ -182,31 +184,34 @@ ptrace_set_bpt(struct task_struct * child) ...@@ -182,31 +184,34 @@ ptrace_set_bpt(struct task_struct * child)
* branch (emulation can be tricky for fp branches). * branch (emulation can be tricky for fp branches).
*/ */
displ = ((s32)(insn << 11)) >> 9; displ = ((s32)(insn << 11)) >> 9;
child->thread.bpt_addr[nsaved++] = pc + 4; child->thread_info->bpt_addr[nsaved++] = pc + 4;
if (displ) /* guard against unoptimized code */ if (displ) /* guard against unoptimized code */
child->thread.bpt_addr[nsaved++] = pc + 4 + displ; child->thread_info->bpt_addr[nsaved++]
= pc + 4 + displ;
DBG(DBG_BPT, ("execing branch\n")); DBG(DBG_BPT, ("execing branch\n"));
} else if (op_code == 0x1a) { } else if (op_code == 0x1a) {
reg_b = (insn >> 16) & 0x1f; reg_b = (insn >> 16) & 0x1f;
child->thread.bpt_addr[nsaved++] = get_reg(child, reg_b); child->thread_info->bpt_addr[nsaved++] = get_reg(child, reg_b);
DBG(DBG_BPT, ("execing jump\n")); DBG(DBG_BPT, ("execing jump\n"));
} else { } else {
child->thread.bpt_addr[nsaved++] = pc + 4; child->thread_info->bpt_addr[nsaved++] = pc + 4;
DBG(DBG_BPT, ("execing normal insn\n")); DBG(DBG_BPT, ("execing normal insn\n"));
} }
/* install breakpoints: */ /* install breakpoints: */
for (i = 0; i < nsaved; ++i) { for (i = 0; i < nsaved; ++i) {
res = read_int(child, child->thread.bpt_addr[i], &insn); res = read_int(child, child->thread_info->bpt_addr[i], &insn);
if (res < 0) if (res < 0)
return res; return res;
child->thread.bpt_insn[i] = insn; child->thread_info->bpt_insn[i] = insn;
DBG(DBG_BPT, (" -> next_pc=%lx\n", child->thread.bpt_addr[i])); DBG(DBG_BPT, (" -> next_pc=%lx\n",
res = write_int(child, child->thread.bpt_addr[i], BREAKINST); child->thread_info->bpt_addr[i]));
res = write_int(child, child->thread_info->bpt_addr[i],
BREAKINST);
if (res < 0) if (res < 0)
return res; return res;
} }
child->thread.bpt_nsaved = nsaved; child->thread_info->bpt_nsaved = nsaved;
return 0; return 0;
} }
...@@ -217,9 +222,9 @@ ptrace_set_bpt(struct task_struct * child) ...@@ -217,9 +222,9 @@ ptrace_set_bpt(struct task_struct * child)
int int
ptrace_cancel_bpt(struct task_struct * child) ptrace_cancel_bpt(struct task_struct * child)
{ {
int i, nsaved = child->thread.bpt_nsaved; int i, nsaved = child->thread_info->bpt_nsaved;
child->thread.bpt_nsaved = 0; child->thread_info->bpt_nsaved = 0;
if (nsaved > 2) { if (nsaved > 2) {
printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
...@@ -227,8 +232,8 @@ ptrace_cancel_bpt(struct task_struct * child) ...@@ -227,8 +232,8 @@ ptrace_cancel_bpt(struct task_struct * child)
} }
for (i = 0; i < nsaved; ++i) { for (i = 0; i < nsaved; ++i) {
write_int(child, child->thread.bpt_addr[i], write_int(child, child->thread_info->bpt_addr[i],
child->thread.bpt_insn[i]); child->thread_info->bpt_insn[i]);
} }
return (nsaved != 0); return (nsaved != 0);
} }
...@@ -335,9 +340,9 @@ sys_ptrace(long request, long pid, long addr, long data, ...@@ -335,9 +340,9 @@ sys_ptrace(long request, long pid, long addr, long data,
if ((unsigned long) data > _NSIG) if ((unsigned long) data > _NSIG)
goto out; goto out;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
child->ptrace |= PT_TRACESYS; set_thread_flag(TIF_SYSCALL_TRACE);
else else
child->ptrace &= ~PT_TRACESYS; clear_thread_flag(TIF_SYSCALL_TRACE);
child->exit_code = data; child->exit_code = data;
wake_up_process(child); wake_up_process(child);
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
...@@ -364,8 +369,9 @@ sys_ptrace(long request, long pid, long addr, long data, ...@@ -364,8 +369,9 @@ sys_ptrace(long request, long pid, long addr, long data,
ret = -EIO; ret = -EIO;
if ((unsigned long) data > _NSIG) if ((unsigned long) data > _NSIG)
goto out; goto out;
child->thread.bpt_nsaved = -1; /* mark single-stepping */ /* Mark single stepping. */
child->ptrace &= ~PT_TRACESYS; child->thread_info->bpt_nsaved = -1;
clear_thread_flag(TIF_SYSCALL_TRACE);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
...@@ -381,7 +387,7 @@ sys_ptrace(long request, long pid, long addr, long data, ...@@ -381,7 +387,7 @@ sys_ptrace(long request, long pid, long addr, long data,
goto out; goto out;
} }
out: out:
free_task_struct(child); put_task_struct(child);
out_notsk: out_notsk:
unlock_kernel(); unlock_kernel();
return ret; return ret;
...@@ -390,8 +396,9 @@ sys_ptrace(long request, long pid, long addr, long data, ...@@ -390,8 +396,9 @@ sys_ptrace(long request, long pid, long addr, long data,
asmlinkage void asmlinkage void
syscall_trace(void) syscall_trace(void)
{ {
if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) if (!test_thread_flag(TIF_SYSCALL_TRACE))
!= (PT_PTRACED|PT_TRACESYS)) return;
if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage void ret_from_sys_call(void); asmlinkage void ret_from_sys_call(void);
asmlinkage int do_signal(sigset_t *, struct pt_regs *, static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *,
struct switch_stack *, unsigned long, unsigned long); unsigned long, unsigned long);
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
...@@ -618,7 +618,7 @@ syscall_restart(unsigned long r0, unsigned long r19, ...@@ -618,7 +618,7 @@ syscall_restart(unsigned long r0, unsigned long r19,
* restart. "r0" is also used as an indicator whether we can restart at * restart. "r0" is also used as an indicator whether we can restart at
* all (if we get here from anything but a syscall return, it will be 0) * all (if we get here from anything but a syscall return, it will be 0)
*/ */
asmlinkage int static int
do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
unsigned long r0, unsigned long r19) unsigned long r0, unsigned long r19)
{ {
...@@ -744,3 +744,12 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, ...@@ -744,3 +744,12 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
return 0; return 0;
} }
void
do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
struct switch_stack *sw, unsigned long r0,
unsigned long r19, unsigned long thread_info_flags)
{
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(oldset, regs, sw, r0, r19);
}
...@@ -131,8 +131,8 @@ dik_show_trace(unsigned long *sp) ...@@ -131,8 +131,8 @@ dik_show_trace(unsigned long *sp)
void show_trace_task(struct task_struct * tsk) void show_trace_task(struct task_struct * tsk)
{ {
struct thread_struct * thread = &tsk->thread; struct thread_info *ti = tsk->thread_info;
unsigned long fp, sp = thread->ksp, base = (unsigned long) thread; unsigned long fp, sp = ti->pcb.ksp, base = (unsigned long) ti;
if (sp > base && sp+6*8 < base + 16*1024) { if (sp > base && sp+6*8 < base + 16*1024) {
fp = ((unsigned long*)sp)[6]; fp = ((unsigned long*)sp)[6];
...@@ -180,12 +180,11 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) ...@@ -180,12 +180,11 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
dik_show_trace((unsigned long *)(regs+1)); dik_show_trace((unsigned long *)(regs+1));
dik_show_code((unsigned int *)regs->pc); dik_show_code((unsigned int *)regs->pc);
if (current->thread.flags & (1UL << 63)) { if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
printk("die_if_kernel recursion detected.\n"); printk("die_if_kernel recursion detected.\n");
sti(); sti();
while (1); while (1);
} }
current->thread.flags |= (1UL << 63);
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
...@@ -232,6 +231,13 @@ do_entIF(unsigned long type, unsigned long a1, ...@@ -232,6 +231,13 @@ do_entIF(unsigned long type, unsigned long a1,
unsigned long a5, struct pt_regs regs) unsigned long a5, struct pt_regs regs)
{ {
if (!opDEC_testing || type != 4) { if (!opDEC_testing || type != 4) {
if (type == 1) {
const unsigned int *data
= (const unsigned int *) regs.pc;
printk("Kernel bug at %s:%d\n",
(const char *)(data[1] | (long)data[2] << 32),
data[0]);
}
die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
&regs, type, 0); &regs, type, 0);
} }
...@@ -324,8 +330,8 @@ do_entIF(unsigned long type, unsigned long a1, ...@@ -324,8 +330,8 @@ do_entIF(unsigned long type, unsigned long a1,
FP registers, PAL_clrfen is not useful except for DoS FP registers, PAL_clrfen is not useful except for DoS
attacks. So turn the bleeding FPU back on and be done attacks. So turn the bleeding FPU back on and be done
with it. */ with it. */
current->thread.pal_flags |= 1; current_thread_info()->pcb.flags |= 1;
__reload_thread(&current->thread); __reload_thread(&current_thread_info()->pcb);
return; return;
case 5: /* illoc */ case 5: /* illoc */
...@@ -605,12 +611,11 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, ...@@ -605,12 +611,11 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
dik_show_code((unsigned int *)pc); dik_show_code((unsigned int *)pc);
dik_show_trace((unsigned long *)(&regs+1)); dik_show_trace((unsigned long *)(&regs+1));
if (current->thread.flags & (1UL << 63)) { if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
printk("die_if_kernel recursion detected.\n"); printk("die_if_kernel recursion detected.\n");
sti(); sti();
while (1); while (1);
} }
current->thread.flags |= (1UL << 63);
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
...@@ -706,14 +711,12 @@ do_entUnaUser(void * va, unsigned long opcode, ...@@ -706,14 +711,12 @@ do_entUnaUser(void * va, unsigned long opcode,
unsigned long tmp1, tmp2, tmp3, tmp4; unsigned long tmp1, tmp2, tmp3, tmp4;
unsigned long fake_reg, *reg_addr = &fake_reg; unsigned long fake_reg, *reg_addr = &fake_reg;
unsigned long uac_bits;
long error; long error;
/* Check the UAC bits to decide what the user wants us to do /* Check the UAC bits to decide what the user wants us to do
with the unaliged access. */ with the unaliged access. */
uac_bits = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (!test_thread_flag (TIF_UAC_NOPRINT)) {
if (!(uac_bits & UAC_NOPRINT)) {
if (cnt >= 5 && jiffies - last_time > 5*HZ) { if (cnt >= 5 && jiffies - last_time > 5*HZ) {
cnt = 0; cnt = 0;
} }
...@@ -724,13 +727,11 @@ do_entUnaUser(void * va, unsigned long opcode, ...@@ -724,13 +727,11 @@ do_entUnaUser(void * va, unsigned long opcode,
} }
last_time = jiffies; last_time = jiffies;
} }
if (uac_bits & UAC_SIGBUS) { if (test_thread_flag (TIF_UAC_SIGBUS))
goto give_sigbus; goto give_sigbus;
} /* Not sure why you'd want to use this, but... */
if (uac_bits & UAC_NOFIX) { if (test_thread_flag (TIF_UAC_NOFIX))
/* Not sure why you'd want to use this, but... */
return; return;
}
/* Don't bother reading ds in the access check since we already /* Don't bother reading ds in the access check since we already
know that this came from the user. Also rely on the fact that know that this came from the user. Also rely on the fact that
......
...@@ -236,7 +236,7 @@ end_b: ...@@ -236,7 +236,7 @@ end_b:
* entry point. * entry point.
*/ */
.align 4 .align 4
.ent __memset .ent __constant_c_memset
__constant_c_memset: __constant_c_memset:
.frame $30,0,$26,0 .frame $30,0,$26,0
.prologue 0 .prologue 0
......
...@@ -114,7 +114,7 @@ alpha_fp_emul (unsigned long pc) ...@@ -114,7 +114,7 @@ alpha_fp_emul (unsigned long pc)
mode = (insn >> 11) & 0x3; mode = (insn >> 11) & 0x3;
fpcr = rdfpcr(); fpcr = rdfpcr();
swcr = swcr_update_status(current->thread.flags, fpcr); swcr = swcr_update_status(current_thread_info()->ieee_state, fpcr);
if (mode == 3) { if (mode == 3) {
/* Dynamic -- get rounding mode from fpcr. */ /* Dynamic -- get rounding mode from fpcr. */
...@@ -297,7 +297,8 @@ alpha_fp_emul (unsigned long pc) ...@@ -297,7 +297,8 @@ alpha_fp_emul (unsigned long pc)
if (_fex) { if (_fex) {
/* Record exceptions in software control word. */ /* Record exceptions in software control word. */
swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
current->thread.flags |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); current_thread_info()->ieee_state
|= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
/* Update hardware control register. */ /* Update hardware control register. */
fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
......
...@@ -43,14 +43,16 @@ extern void ...@@ -43,14 +43,16 @@ extern void
__load_new_mm_context(struct mm_struct *next_mm) __load_new_mm_context(struct mm_struct *next_mm)
{ {
unsigned long mmc; unsigned long mmc;
struct pcb_struct *pcb;
mmc = __get_new_mm_context(next_mm, smp_processor_id()); mmc = __get_new_mm_context(next_mm, smp_processor_id());
next_mm->context[smp_processor_id()] = mmc; next_mm->context[smp_processor_id()] = mmc;
current->thread.asn = mmc & HARDWARE_ASN_MASK;
current->thread.ptbr
= ((unsigned long) next_mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
__reload_thread(&current->thread); pcb = &current_thread_info()->pcb;
pcb->asn = mmc & HARDWARE_ASN_MASK;
pcb->ptbr = ((unsigned long) next_mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
__reload_thread(pcb);
} }
......
...@@ -40,7 +40,7 @@ unsigned long totalram_pages; ...@@ -40,7 +40,7 @@ unsigned long totalram_pages;
extern void die_if_kernel(char *,struct pt_regs *,long); extern void die_if_kernel(char *,struct pt_regs *,long);
struct thread_struct original_pcb; static struct pcb_struct original_pcb;
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
struct pgtable_cache_struct quicklists; struct pgtable_cache_struct quicklists;
...@@ -151,7 +151,7 @@ show_mem(void) ...@@ -151,7 +151,7 @@ show_mem(void)
#endif #endif
static inline unsigned long static inline unsigned long
load_PCB(struct thread_struct * pcb) load_PCB(struct pcb_struct *pcb)
{ {
register unsigned long sp __asm__("$30"); register unsigned long sp __asm__("$30");
pcb->ksp = sp; pcb->ksp = sp;
...@@ -182,10 +182,9 @@ switch_to_system_map(void) ...@@ -182,10 +182,9 @@ switch_to_system_map(void)
} }
/* Also set up the real kernel PCB while we're at it. */ /* Also set up the real kernel PCB while we're at it. */
init_task.thread.ptbr = newptbr; init_thread_info.pcb.ptbr = newptbr;
init_task.thread.pal_flags = 1; /* set FEN, clear everything else */ init_thread_info.pcb.flags = 1; /* set FEN, clear everything else */
init_task.thread.flags = 0; original_pcb_ptr = load_PCB(&init_thread_info.pcb);
original_pcb_ptr = load_PCB(&init_task.thread);
tbia(); tbia();
/* Save off the contents of the original PCB so that we can /* Save off the contents of the original PCB so that we can
...@@ -199,7 +198,7 @@ switch_to_system_map(void) ...@@ -199,7 +198,7 @@ switch_to_system_map(void)
original_pcb_ptr = (unsigned long) original_pcb_ptr = (unsigned long)
phys_to_virt(original_pcb_ptr); phys_to_virt(original_pcb_ptr);
} }
original_pcb = *(struct thread_struct *) original_pcb_ptr; original_pcb = *(struct pcb_struct *) original_pcb_ptr;
} }
int callback_init_done; int callback_init_done;
...@@ -270,7 +269,7 @@ callback_init(void * kernel_end) ...@@ -270,7 +269,7 @@ callback_init(void * kernel_end)
/* Let vmalloc know that we've allocated some space. */ /* Let vmalloc know that we've allocated some space. */
console_remap_vm.flags = VM_ALLOC; console_remap_vm.flags = VM_ALLOC;
console_remap_vm.addr = VMALLOC_START; console_remap_vm.addr = (void *) VMALLOC_START;
console_remap_vm.size = vaddr - VMALLOC_START; console_remap_vm.size = vaddr - VMALLOC_START;
vmlist = &console_remap_vm; vmlist = &console_remap_vm;
} }
......
...@@ -11,37 +11,42 @@ SECTIONS ...@@ -11,37 +11,42 @@ SECTIONS
. = 0xfffffc0000810000; . = 0xfffffc0000810000;
#endif #endif
_text = .; .text : {
.text : { *(.text) } :kernel _text = .;
_etext = .; *(.text)
_etext = .;
} :kernel
/* Exception table */ /* Exception table */
. = ALIGN(16); __ex_table ALIGN(16) : {
__start___ex_table = .; __start___ex_table = .;
__ex_table : { *(__ex_table) } *(__ex_table)
__stop___ex_table = .; __stop___ex_table = .;
}
/* Kernel symbol table */ /* Kernel symbol table */
. = ALIGN(8); __ksymtab ALIGN(8) : {
__start___ksymtab = .; __start___ksymtab = .;
__ksymtab : { *(__ksymtab) } *(__ksymtab)
__stop___ksymtab = .; __stop___ksymtab = .;
}
.kstrtab : { *(.kstrtab) } .kstrtab : { *(.kstrtab) }
/* Startup code */ /* Startup code */
. = ALIGN(8192); .text.init ALIGN(8192) : {
__init_begin = .; __init_begin = .;
.text.init : { *(.text.init) } *(.text.init)
}
.data.init : { *(.data.init) } .data.init : { *(.data.init) }
. = ALIGN(16); .setup.init ALIGN(16): {
__setup_start = .; __setup_start = .;
.setup.init : { *(.setup.init) } *(.setup.init)
__setup_end = .; __setup_end = .;
}
. = ALIGN(8); .initcall.init ALIGN(8): {
__initcall_start = .; __initcall_start = .;
.initcall.init : {
*(.initcall1.init) *(.initcall1.init)
*(.initcall2.init) *(.initcall2.init)
*(.initcall3.init) *(.initcall3.init)
...@@ -49,29 +54,37 @@ SECTIONS ...@@ -49,29 +54,37 @@ SECTIONS
*(.initcall5.init) *(.initcall5.init)
*(.initcall6.init) *(.initcall6.init)
*(.initcall7.init) *(.initcall7.init)
__initcall_end = .;
} }
__initcall_end = .;
. = ALIGN(2*8192); /* Align double page for init_task_union */
__init_end = .;
/* The initial task and kernel stack */ /* The initial task and kernel stack */
init_task : { *(init_task) } .data.init_thread ALIGN(2*8192) : {
__init_end = .;
*(.data.init_thread)
}
/* Global data */ /* Global data */
_data = .; .data.cacheline_aligned : {
.data.cacheline_aligned : { *(.data.cacheline_aligned) } _data = .;
*(.data.cacheline_aligned)
}
.rodata : { *(.rodata) *(.rodata.*) } .rodata : { *(.rodata) *(.rodata.*) }
.data : { *(.data) CONSTRUCTORS } .data : { *(.data) CONSTRUCTORS }
.got : { *(.got) } .got : { *(.got) }
.sdata : { *(.sdata) } .sdata : {
_edata = .; *(.sdata)
_edata = .;
}
__bss_start = .; .sbss : {
.sbss : { *(.sbss) *(.scommon) } __bss_start = .;
.bss : { *(.bss) *(COMMON) } *(.sbss) *(.scommon)
__bss_stop = .; }
_end = .; .bss : {
*(.bss) *(COMMON)
__bss_stop = .;
_end = .;
}
.mdebug 0 : { *(.mdebug) } .mdebug 0 : { *(.mdebug) }
.note 0 : { *(.note) } .note 0 : { *(.note) }
......
#ifndef __ASM_OFFSETS_H__
#define __ASM_OFFSETS_H__
#define TASK_STATE 0
#define TASK_FLAGS 8
#define TASK_SIGPENDING 16
#define TASK_ADDR_LIMIT 24
#define TASK_EXEC_DOMAIN 32
#define TASK_NEED_RESCHED 40
#define TASK_SIZE 1096
#define STACK_SIZE 16384
#define HAE_CACHE 0
#define HAE_REG 8
#endif /* __ASM_OFFSETS_H__ */
...@@ -74,11 +74,11 @@ clear_bit(unsigned long nr, volatile void * addr) ...@@ -74,11 +74,11 @@ clear_bit(unsigned long nr, volatile void * addr)
* WARNING: non atomic version. * WARNING: non atomic version.
*/ */
static __inline__ void static __inline__ void
__change_bit(unsigned long nr, volatile void * addr) __clear_bit(unsigned long nr, volatile void * addr)
{ {
int *m = ((int *) addr) + (nr >> 5); int *m = ((int *) addr) + (nr >> 5);
*m ^= 1 << (nr & 31); *m &= ~(1 << (nr & 31));
} }
static inline void static inline void
...@@ -99,6 +99,17 @@ change_bit(unsigned long nr, volatile void * addr) ...@@ -99,6 +99,17 @@ change_bit(unsigned long nr, volatile void * addr)
:"Ir" (1UL << (nr & 31)), "m" (*m)); :"Ir" (1UL << (nr & 31)), "m" (*m));
} }
/*
* WARNING: non atomic version.
*/
static __inline__ void
__change_bit(unsigned long nr, volatile void * addr)
{
int *m = ((int *) addr) + (nr >> 5);
*m ^= 1 << (nr & 31);
}
static inline int static inline int
test_and_set_bit(unsigned long nr, volatile void *addr) test_and_set_bit(unsigned long nr, volatile void *addr)
{ {
...@@ -181,20 +192,6 @@ __test_and_clear_bit(unsigned long nr, volatile void * addr) ...@@ -181,20 +192,6 @@ __test_and_clear_bit(unsigned long nr, volatile void * addr)
return (old & mask) != 0; return (old & mask) != 0;
} }
/*
* WARNING: non atomic version.
*/
static __inline__ int
__test_and_change_bit(unsigned long nr, volatile void * addr)
{
unsigned long mask = 1 << (nr & 0x1f);
int *m = ((int *) addr) + (nr >> 5);
int old = *m;
*m = old ^ mask;
return (old & mask) != 0;
}
static inline int static inline int
test_and_change_bit(unsigned long nr, volatile void * addr) test_and_change_bit(unsigned long nr, volatile void * addr)
{ {
...@@ -220,6 +217,20 @@ test_and_change_bit(unsigned long nr, volatile void * addr) ...@@ -220,6 +217,20 @@ test_and_change_bit(unsigned long nr, volatile void * addr)
return oldbit != 0; return oldbit != 0;
} }
/*
* WARNING: non atomic version.
*/
static __inline__ int
__test_and_change_bit(unsigned long nr, volatile void * addr)
{
unsigned long mask = 1 << (nr & 0x1f);
int *m = ((int *) addr) + (nr >> 5);
int old = *m;
*m = old ^ mask;
return (old & mask) != 0;
}
static inline int static inline int
test_bit(int nr, volatile void * addr) test_bit(int nr, volatile void * addr)
{ {
...@@ -264,17 +275,39 @@ static inline unsigned long ffz(unsigned long word) ...@@ -264,17 +275,39 @@ static inline unsigned long ffz(unsigned long word)
#endif #endif
} }
/*
* __ffs = Find First set bit in word. Undefined if no set bit exists.
*/
static inline unsigned long __ffs(unsigned long word)
{
#if defined(__alpha_cix__) && defined(__alpha_fix__)
/* Whee. EV67 can calculate it directly. */
unsigned long result;
__asm__("cttz %1,%0" : "=r"(result) : "r"(word));
return result;
#else
unsigned long bits, qofs, bofs;
__asm__("cmpbge $31,%1,%0" : "=r"(bits) : "r"(word));
qofs = ffz_b(bits);
__asm__("extbl %1,%2,%0" : "=r"(bits) : "r"(word), "r"(qofs));
bofs = ffz_b(~bits);
return qofs*8 + bofs;
#endif
}
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*
* ffs: find first bit set. This is defined the same way as * ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore * the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs). * differs in spirit from the above __ffs.
*/ */
static inline int ffs(int word) static inline int ffs(int word)
{ {
int result = ffz(~word); int result = __ffs(word);
return word ? result+1 : 0; return word ? result+1 : 0;
} }
...@@ -365,10 +398,53 @@ find_next_zero_bit(void * addr, unsigned long size, unsigned long offset) ...@@ -365,10 +398,53 @@ find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
} }
/* /*
* The optimizer actually does good code for this case.. * Find next one bit in a bitmap reasonably efficiently.
*/
static inline unsigned long
find_next_bit(void * addr, unsigned long size, unsigned long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 63UL;
if (offset) {
tmp = *(p++);
tmp &= ~0UL << offset;
if (size < 64)
goto found_first;
if (tmp)
goto found_middle;
size -= 64;
result += 64;
}
while (size & ~63UL) {
if ((tmp = *(p++)))
goto found_middle;
result += 64;
size -= 64;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp &= ~0UL >> (64 - size);
if (!tmp)
return result + size;
found_middle:
return result + __ffs(tmp);
}
/*
* The optimizer actually does good code for this case.
*/ */
#define find_first_zero_bit(addr, size) \ #define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0) find_next_zero_bit((addr), (size), 0)
#define find_first_bit(addr, size) \
find_next_bit((addr), (size), 0)
#ifdef __KERNEL__ #ifdef __KERNEL__
......
#ifndef _ALPHA_CURRENT_H #ifndef _ALPHA_CURRENT_H
#define _ALPHA_CURRENT_H #define _ALPHA_CURRENT_H
register struct task_struct *current __asm__("$8"); #include <asm/thread_info.h>
#endif /* !(_ALPHA_CURRENT_H) */ #define get_current() (current_thread_info()->task + 0)
#define current get_current()
#endif /* _ALPHA_CURRENT_H */
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
/* /*
* IEEE trap enables are implemented in software. These per-thread * IEEE trap enables are implemented in software. These per-thread
* bits are stored in the "flags" field of "struct thread_struct". * bits are stored in the "ieee_state" field of "struct thread_info".
* Thus, the bits are defined so as not to conflict with the * Thus, the bits are defined so as not to conflict with the
* floating-point enable bit (which is architected). On top of that, * floating-point enable bit (which is architected). On top of that,
* we want to make these bits compatible with OSF/1 so * we want to make these bits compatible with OSF/1 so
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/machvec.h> #include <asm/machvec.h>
/* /*
...@@ -60,7 +61,10 @@ static inline void * phys_to_virt(unsigned long address) ...@@ -60,7 +61,10 @@ static inline void * phys_to_virt(unsigned long address)
return (void *) (address + IDENT_ADDR); return (void *) (address + IDENT_ADDR);
} }
#define page_to_phys(page) (((page) - (page)->zone->zone_mem_map) << PAGE_SHIFT) #define page_to_phys(page) PAGE_TO_PA(page)
/* This depends on working iommu. */
#define BIO_VMERGE_BOUNDARY (alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
/* /*
* Change addresses as seen by the kernel (virtual) to addresses as * Change addresses as seen by the kernel (virtual) to addresses as
......
...@@ -21,8 +21,34 @@ ...@@ -21,8 +21,34 @@
#include <asm/io.h> #include <asm/io.h>
#endif #endif
/* ??? This does not belong here. */
/*
* Every architecture must define this function. It's the fastest
* way of searching a 168-bit bitmap where the first 128 bits are
* unlikely to be set. It's guaranteed that at least one of the 168
* bits is set.
*/
#if MAX_RT_PRIO != 128 || MAX_PRIO > 192
# error update this function.
#endif
static inline int
sched_find_first_bit(unsigned long *b)
{
unsigned long b0 = b[0], b1 = b[1], b2 = b[2];
unsigned long offset = 128;
if (unlikely(b0 | b1)) {
b2 = (b0 ? b0 : b1);
offset = (b0 ? 0 : 64);
}
return __ffs(b2) + offset;
}
extern inline unsigned long extern inline unsigned long
__reload_thread(struct thread_struct *pcb) __reload_thread(struct pcb_struct *pcb)
{ {
register unsigned long a0 __asm__("$16"); register unsigned long a0 __asm__("$16");
register unsigned long v0 __asm__("$0"); register unsigned long v0 __asm__("$0");
...@@ -153,7 +179,7 @@ ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, ...@@ -153,7 +179,7 @@ ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
/* Always update the PCB ASN. Another thread may have allocated /* Always update the PCB ASN. Another thread may have allocated
a new mm->context (via flush_tlb_mm) without the ASN serial a new mm->context (via flush_tlb_mm) without the ASN serial
number wrapping. We have no way to detect when this is needed. */ number wrapping. We have no way to detect when this is needed. */
next->thread.asn = mmc & HARDWARE_ASN_MASK; next->thread_info->pcb.asn = mmc & HARDWARE_ASN_MASK;
} }
__EXTERN_INLINE void __EXTERN_INLINE void
...@@ -228,7 +254,8 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) ...@@ -228,7 +254,8 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
for (i = 0; i < smp_num_cpus; i++) for (i = 0; i < smp_num_cpus; i++)
mm->context[cpu_logical_map(i)] = 0; mm->context[cpu_logical_map(i)] = 0;
tsk->thread.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; tsk->thread_info->pcb.ptbr
= ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
return 0; return 0;
} }
...@@ -241,7 +268,8 @@ destroy_context(struct mm_struct *mm) ...@@ -241,7 +268,8 @@ destroy_context(struct mm_struct *mm)
static inline void static inline void
enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{ {
tsk->thread.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; tsk->thread_info->pcb.ptbr
= ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
} }
#ifdef __MMU_EXTERN_INLINE #ifdef __MMU_EXTERN_INLINE
......
...@@ -59,11 +59,11 @@ typedef unsigned long pgprot_t; ...@@ -59,11 +59,11 @@ typedef unsigned long pgprot_t;
#endif /* STRICT_MM_TYPECHECKS */ #endif /* STRICT_MM_TYPECHECKS */
#define BUG() \ /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
do { \ function loaded the GP, so this could fail in modules. */
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ #define BUG() \
__asm__ __volatile__("call_pal %0 # bugchk" : : "i" (PAL_bugchk)); \ __asm__ __volatile__("call_pal %0 # bugchk\n\t"".long %1\n\t.8byte %2" \
} while (0) : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
#define PAGE_BUG(page) BUG() #define PAGE_BUG(page) BUG()
......
...@@ -38,83 +38,17 @@ typedef struct { ...@@ -38,83 +38,17 @@ typedef struct {
unsigned long seg; unsigned long seg;
} mm_segment_t; } mm_segment_t;
struct thread_struct { /* This is dead. Everything has been moved to thread_info. */
/* the fields below are used by PALcode and must match struct pcb: */ struct thread_struct { };
unsigned long ksp; #define INIT_THREAD { }
unsigned long usp;
unsigned long ptbr;
unsigned int pcc;
unsigned int asn;
unsigned long unique;
/*
* bit 0: floating point enable
* bit 62: performance monitor enable
*/
unsigned long pal_flags;
unsigned long res1, res2;
/*
* The fields below are Linux-specific:
*
* bit 1..5: IEEE_TRAP_ENABLE bits (see fpu.h)
* bit 6..8: UAC bits (see sysinfo.h)
* bit 17..21: IEEE_STATUS_MASK bits (see fpu.h)
* bit 63: die_if_kernel recursion lock
*/
unsigned long flags;
/* Perform syscall argument validation (get/set_fs). */
mm_segment_t fs;
/* Breakpoint handling for ptrace. */
unsigned long bpt_addr[2];
unsigned int bpt_insn[2];
int bpt_nsaved;
};
#define INIT_THREAD { \
0, 0, 0, \
0, 0, 0, \
0, 0, 0, \
0, \
KERNEL_DS \
}
#define THREAD_SIZE (2*PAGE_SIZE)
#include <asm/ptrace.h> /* Return saved PC of a blocked thread. */
struct task_struct;
/* extern unsigned long thread_saved_pc(struct task_struct *);
* Return saved PC of a blocked thread. This assumes the frame
* pointer is the 6th saved long on the kernel stack and that the
* saved return address is the first long in the frame. This all
* holds provided the thread blocked through a call to schedule() ($15
* is the frame pointer in schedule() and $15 is saved at offset 48 by
* entry.S:do_switch_stack).
*
* Under heavy swap load I've seen this lose in an ugly way. So do
* some extra sanity checking on the ranges we expect these pointers
* to be in so that we can fail gracefully. This is just for ps after
* all. -- r~
*/
extern inline unsigned long thread_saved_pc(struct thread_struct *t)
{
unsigned long fp, sp = t->ksp, base = (unsigned long)t;
if (sp > base && sp+6*8 < base + 16*1024) {
fp = ((unsigned long*)sp)[6];
if (fp > sp && fp < base + 16*1024)
return *(unsigned long *)fp;
}
return 0;
}
/* Do necessary setup to start up a newly executed thread. */ /* Do necessary setup to start up a newly executed thread. */
extern void start_thread(struct pt_regs *, unsigned long, unsigned long); extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
struct task_struct;
/* Free all resources held by a thread. */ /* Free all resources held by a thread. */
extern void release_thread(struct task_struct *); extern void release_thread(struct task_struct *);
...@@ -127,26 +61,18 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); ...@@ -127,26 +61,18 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
unsigned long get_wchan(struct task_struct *p); unsigned long get_wchan(struct task_struct *p);
/* See arch/alpha/kernel/ptrace.c for details. */ /* See arch/alpha/kernel/ptrace.c for details. */
#define PT_REG(reg) (PAGE_SIZE*2 - sizeof(struct pt_regs) \ #define PT_REG(reg) \
+ (long)&((struct pt_regs *)0)->reg) (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg))
#define SW_REG(reg) (PAGE_SIZE*2 - sizeof(struct pt_regs) \ #define SW_REG(reg) \
- sizeof(struct switch_stack) \ (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
+ (long)&((struct switch_stack *)0)->reg) + offsetof(struct switch_stack, reg))
#define KSTK_EIP(tsk) \ #define KSTK_EIP(tsk) \
(*(unsigned long *)(PT_REG(pc) + (unsigned long)(tsk))) (*(unsigned long *)(PT_REG(pc) + (unsigned long) ((tsk)->thread_info)))
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
/* NOTE: The task struct and the stack go together! */
#define alloc_task_struct() \
((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
#define free_task_struct(p) free_pages((unsigned long)(p),1)
#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
#define init_task (init_task_union.task) #define KSTK_ESP(tsk) \
#define init_stack (init_task_union.stack) ((tsk) == current ? rdusp() : (tsk)->thread_info->pcb.usp)
#define cpu_relax() do { } while (0) #define cpu_relax() do { } while (0)
...@@ -154,21 +80,36 @@ unsigned long get_wchan(struct task_struct *p); ...@@ -154,21 +80,36 @@ unsigned long get_wchan(struct task_struct *p);
#define ARCH_HAS_PREFETCHW #define ARCH_HAS_PREFETCHW
#define ARCH_HAS_SPINLOCK_PREFETCH #define ARCH_HAS_SPINLOCK_PREFETCH
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
extern inline void prefetch(const void *ptr) extern inline void prefetch(const void *ptr)
{ {
__asm__ ("ldl $31,%0" : : "m"(*(char *)ptr)); __builtin_prefetch(ptr, 0, 3);
} }
extern inline void prefetchw(const void *ptr) extern inline void prefetchw(const void *ptr)
{ {
__asm__ ("ldl $31,%0" : : "m"(*(char *)ptr)); __builtin_prefetch(ptr, 1, 3);
} }
extern inline void spin_lock_prefetch(const void *ptr) extern inline void spin_lock_prefetch(const void *ptr)
{ {
__builtin_prefetch(ptr, 1, 3);
}
#else
extern inline void prefetch(const void *ptr)
{
__asm__ ("ldl $31,%0" : : "m"(*(char *)ptr)); __asm__ ("ldl $31,%0" : : "m"(*(char *)ptr));
} }
extern inline void prefetchw(const void *ptr)
{
__asm__ ("ldq $31,%0" : : "m"(*(char *)ptr));
}
extern inline void spin_lock_prefetch(const void *ptr)
{
__asm__ ("ldq $31,%0" : : "m"(*(char *)ptr));
}
#endif /* GCC 3.1 */
#endif /* __ASM_ALPHA_PROCESSOR_H */ #endif /* __ASM_ALPHA_PROCESSOR_H */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __ASM_SMP_H #define __ASM_SMP_H
#include <linux/config.h> #include <linux/config.h>
#include <linux/threads.h>
#include <asm/pal.h> #include <asm/pal.h>
/* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */ /* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */
...@@ -55,7 +56,7 @@ extern int __cpu_logical_map[NR_CPUS]; ...@@ -55,7 +56,7 @@ extern int __cpu_logical_map[NR_CPUS];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu] #define cpu_logical_map(cpu) __cpu_logical_map[cpu]
#define hard_smp_processor_id() __hard_smp_processor_id() #define hard_smp_processor_id() __hard_smp_processor_id()
#define smp_processor_id() (current->processor) #define smp_processor_id() (current_thread_info()->cpu)
extern unsigned long cpu_present_mask; extern unsigned long cpu_present_mask;
#define cpu_online_map cpu_present_mask #define cpu_online_map cpu_present_mask
......
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
/* This is the shift that is applied to the UAC bits as stored in the /* This is the shift that is applied to the UAC bits as stored in the
per-thread flags. */ per-thread flags. See thread_info.h. */
#define UAC_SHIFT 6 #define UAC_SHIFT 6
#endif #endif
......
...@@ -134,8 +134,7 @@ extern void halt(void) __attribute__((noreturn)); ...@@ -134,8 +134,7 @@ extern void halt(void) __attribute__((noreturn));
#define switch_to(prev,next,last) \ #define switch_to(prev,next,last) \
do { \ do { \
unsigned long pcbb; \ unsigned long pcbb; \
current = (next); \ pcbb = virt_to_phys(&(next)->thread_info->pcb); \
pcbb = virt_to_phys(&current->thread); \
(last) = alpha_switch_to(pcbb, (prev)); \ (last) = alpha_switch_to(pcbb, (prev)); \
check_mmu_context(); \ check_mmu_context(); \
} while (0) } while (0)
......
#ifndef _ALPHA_THREAD_INFO_H
#define _ALPHA_THREAD_INFO_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <asm/processor.h>
#include <asm/types.h>
#include <asm/hwrpb.h>
#endif
#ifndef __ASSEMBLY__
struct thread_info {
struct pcb_struct pcb; /* palcode state */
struct task_struct *task; /* main task structure */
unsigned int flags; /* low level flags */
unsigned int ieee_state; /* see fpu.h */
struct exec_domain *exec_domain; /* execution domain */
mm_segment_t addr_limit; /* thread address space */
int cpu; /* current CPU */
int bpt_nsaved;
unsigned long bpt_addr[2]; /* breakpoint handling */
unsigned int bpt_insn[2];
};
/*
* Macros/functions for gaining access to the thread information structure.
*/
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
addr_limit: KERNEL_DS, \
}
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
/* How to get the thread information struct from C. */
register struct thread_info *__current_thread_info __asm__("$8");
#define current_thread_info() __current_thread_info
/* Thread information allocation. */
#define THREAD_SIZE (2*PAGE_SIZE)
#define alloc_thread_info() \
((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
/*
* Thread information flags:
* - these are process state flags and used from assembly
* - pending work-to-be-done flags come first to fit in and immediate operand.
*
* TIF_SYSCALL_TRACE is known to be 0 via blbs.
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_POLLING_NRFLAG 4 /* poll_idle is polling NEED_RESCHED */
#define TIF_DIE_IF_KERNEL 5 /* dik recursion lock */
#define TIF_UAC_NOPRINT 6 /* see sysinfo.h */
#define TIF_UAC_NOFIX 7
#define TIF_UAC_SIGBUS 8
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* Work to do on interrupt/exception return. */
#define _TIF_WORK_MASK (_TIF_NOTIFY_RESUME \
| _TIF_SIGPENDING \
| _TIF_NEED_RESCHED)
/* Work to do on any return to userspace. */
#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \
| _TIF_SYSCALL_TRACE)
#endif /* __KERNEL__ */
#endif /* _ALPHA_THREAD_INFO_H */
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
#define VERIFY_READ 0 #define VERIFY_READ 0
#define VERIFY_WRITE 1 #define VERIFY_WRITE 1
#define get_fs() (current->thread.fs) #define get_fs() (current_thread_info()->addr_limit)
#define get_ds() (KERNEL_DS) #define get_ds() (KERNEL_DS)
#define set_fs(x) (current->thread.fs = (x)) #define set_fs(x) (current_thread_info()->addr_limit = (x))
#define segment_eq(a,b) ((a).seg == (b).seg) #define segment_eq(a,b) ((a).seg == (b).seg)
......
...@@ -506,6 +506,7 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\ ...@@ -506,6 +506,7 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\
#include <linux/string.h> #include <linux/string.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <asm/ptrace.h>
extern void sys_idle(void); extern void sys_idle(void);
static inline void idle(void) static inline void idle(void)
...@@ -576,6 +577,8 @@ static inline long sync(void) ...@@ -576,6 +577,8 @@ static inline long sync(void)
return sys_sync(); return sys_sync();
} }
struct rusage;
extern asmlinkage long sys_wait4(pid_t, unsigned int *, int, struct rusage *);
static inline pid_t waitpid(int pid, int * wait_stat, int flags) static inline pid_t waitpid(int pid, int * wait_stat, int flags)
{ {
return sys_wait4(pid, wait_stat, flags, NULL); return sys_wait4(pid, wait_stat, flags, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment