Commit 77074c5d authored by Jeff Dike's avatar Jeff Dike

Forward ported a number of bug fixes from 2.4, including SA_SIGINFO

signal delivery, protecting skas mode against tmpfs running out of
space, protecting the UML main thread against accidentally running
kernel code, and a couple of data corruption bugs.
parent 6cc944b6
......@@ -15,12 +15,12 @@ struct frame_common {
int sr_index;
int sr_relative;
int sp_index;
struct arch_frame_data arch;
};
struct sc_frame {
struct frame_common common;
int sc_index;
struct arch_frame_data arch;
};
extern struct sc_frame signal_frame_sc;
......@@ -31,6 +31,8 @@ struct si_frame {
struct frame_common common;
int sip_index;
int si_index;
int ucp_index;
int uc_index;
};
extern struct si_frame signal_frame_si;
......
......@@ -8,7 +8,7 @@
enum { IRQ_READ, IRQ_WRITE };
extern void sigio_handler(int sig, struct uml_pt_regs *regs);
extern void sigio_handler(int sig, union uml_pt_regs *regs);
extern int activate_fd(int irq, int fd, int type, void *dev_id);
extern void free_irq_by_irq_and_dev(int irq, void *dev_id);
extern void free_irq_by_fd(int fd);
......
......@@ -47,7 +47,7 @@ extern void free_stack(unsigned long stack, int order);
extern void add_input_request(int op, void (*proc)(int), void *arg);
extern int sys_execve(char *file, char **argv, char **env);
extern char *current_cmd(void);
extern void timer_handler(int sig, struct uml_pt_regs *regs);
extern void timer_handler(int sig, union uml_pt_regs *regs);
extern int set_signals(int enable);
extern void force_sigbus(void);
extern int pid_to_processor_id(int pid);
......@@ -64,7 +64,7 @@ extern void *syscall_sp(void *t);
extern void syscall_trace(void);
extern int hz(void);
extern void idle_timer(void);
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
extern int external_pid(void *t);
extern int pid_to_processor_id(int pid);
extern void boot_timer_handler(int sig);
......@@ -77,10 +77,10 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
extern int init_parent_proxy(int pid);
extern int singlestepping(void *t);
extern void check_stack_overflow(void *ptr);
extern void relay_signal(int sig, struct uml_pt_regs *regs);
extern void relay_signal(int sig, union uml_pt_regs *regs);
extern void not_implemented(void);
extern int user_context(unsigned long sp);
extern void timer_irq(struct uml_pt_regs *regs);
extern void timer_irq(union uml_pt_regs *regs);
extern void unprotect_stack(unsigned long stack);
extern void do_uml_exitcalls(void);
extern int attach_debugger(int idle_pid, int pid, int stop);
......@@ -101,7 +101,7 @@ extern void *get_init_task(void);
extern int clear_user_proc(void *buf, int size);
extern int copy_to_user_proc(void *to, void *from, int size);
extern int copy_from_user_proc(void *to, void *from, int size);
extern void bus_handler(int sig, struct uml_pt_regs *regs);
extern void bus_handler(int sig, union uml_pt_regs *regs);
extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
extern void *get_current(void);
......
......@@ -7,7 +7,8 @@
#define __FRAME_I386_H
struct arch_frame_data_raw {
unsigned long sc_end;
unsigned long fp_start;
unsigned long sr;
};
struct arch_frame_data {
......
......@@ -16,6 +16,15 @@ static inline void *sp_to_sc(unsigned long sp)
return((void *) sp);
}
static inline void *sp_to_uc(unsigned long sp)
{
unsigned long uc;
uc = sp + signal_frame_si.uc_index -
signal_frame_si.common.sp_index - 4;
return((void *) uc);
}
static inline void *sp_to_rt_sc(unsigned long sp)
{
unsigned long sc;
......@@ -42,7 +51,7 @@ static inline void *sp_to_rt_mask(unsigned long sp)
mask = sp - signal_frame_si.common.sp_index +
signal_frame_si.common.len +
sc_size(&signal_frame_sc.arch) - 4;
sc_size(&signal_frame_si.common.arch) - 4;
return((void *) mask);
}
......
......@@ -18,26 +18,35 @@
* setup_arch_frame uses that data to figure out what
* arch_frame_data.fpstate_size should be. It really has no idea, since it's
* not allowed to do sizeof(struct fpstate) but it's safe to consider that it's
* everything from the end of the sgcontext up to the top of the stack. So,
* everything from the end of the sigcontext up to the top of the stack. So,
* it masks off the page number to get the offset within the page and subtracts
* that from the page size, and that's how big the fpstate struct will be
* considered to be.
*/
static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data,
struct sigcontext *sc)
void *end, unsigned long srp)
{
data->sc_end = (unsigned long) sc;
data->sc_end += sizeof(*sc);
unsigned long sr = *((unsigned long *) srp);
data->fp_start = (unsigned long) end;
if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK))
data->sr = sr;
else data->sr = 0;
}
static inline void setup_arch_frame(struct arch_frame_data_raw *in,
struct arch_frame_data *out)
{
unsigned long fpstate_start = in->sc_end;
unsigned long fpstate_start = in->fp_start;
fpstate_start &= ~PAGE_MASK;
out->fpstate_size = PAGE_SIZE - fpstate_start;
if(in->sr == 0){
fpstate_start &= ~PAGE_MASK;
out->fpstate_size = PAGE_SIZE - fpstate_start;
}
else {
out->fpstate_size = in->sr - fpstate_start;
}
}
/* This figures out where on the stack the SA_RESTORER function address
......
......@@ -7,72 +7,101 @@
#define __SYSDEP_I386_PTRACE_H
#include "uml-config.h"
#ifdef CONFIG_MODE_TT
#include "ptrace-tt.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "ptrace-skas.h"
#endif
#include "choose-mode.h"
struct uml_pt_regs {
unsigned long args[6];
long syscall;
int is_user;
union {
union uml_pt_regs {
#ifdef CONFIG_MODE_TT
void *tt;
struct tt_regs {
long syscall;
void *sc;
} tt;
#endif
#ifdef CONFIG_MODE_SKAS
struct {
unsigned long regs[HOST_FRAME_SIZE];
unsigned long fp[HOST_FP_SIZE];
unsigned long xfp[HOST_XFP_SIZE];
unsigned long fault_addr;
unsigned long fault_type;
unsigned long trap_type;
} skas;
struct skas_regs {
unsigned long regs[HOST_FRAME_SIZE];
unsigned long fp[HOST_FP_SIZE];
unsigned long xfp[HOST_XFP_SIZE];
unsigned long fault_addr;
unsigned long fault_type;
unsigned long trap_type;
long syscall;
int is_user;
} skas;
#endif
} mode;
};
#define EMPTY_UML_PT_REGS { \
syscall : -1, \
args : { [0 ... 5] = 0 }, \
is_user : 0 }
#define EMPTY_UML_PT_REGS { }
extern int mode_tt;
#define UPT_SC(r) ((r)->tt.sc)
#define UPT_IP(r) \
CHOOSE_MODE(SC_IP((r)->mode.tt), REGS_IP((r)->mode.skas.regs))
CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
#define UPT_SP(r) \
CHOOSE_MODE(SC_SP((r)->mode.tt), REGS_SP((r)->mode.skas.regs))
CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
#define UPT_EFLAGS(r) \
CHOOSE_MODE(SC_EFLAGS((r)->mode.tt), REGS_EFLAGS((r)->mode.skas.regs))
CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_EAX(r) \
CHOOSE_MODE(SC_EAX((r)->mode.tt), REGS_EAX((r)->mode.skas.regs))
CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs))
#define UPT_EBX(r) \
CHOOSE_MODE(SC_EBX((r)->mode.tt), REGS_EBX((r)->mode.skas.regs))
CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs))
#define UPT_ECX(r) \
CHOOSE_MODE(SC_ECX((r)->mode.tt), REGS_ECX((r)->mode.skas.regs))
CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs))
#define UPT_EDX(r) \
CHOOSE_MODE(SC_EDX((r)->mode.tt), REGS_EDX((r)->mode.skas.regs))
CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs))
#define UPT_ESI(r) \
CHOOSE_MODE(SC_ESI((r)->mode.tt), REGS_ESI((r)->mode.skas.regs))
CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs))
#define UPT_EDI(r) \
CHOOSE_MODE(SC_EDI((r)->mode.tt), REGS_EDI((r)->mode.skas.regs))
CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs))
#define UPT_EBP(r) \
CHOOSE_MODE(SC_EBP((r)->mode.tt), REGS_EBP((r)->mode.skas.regs))
#define UPT_ORIG_EAX(r) ((r)->syscall)
CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs))
#define UPT_ORIG_EAX(r) \
CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
#define UPT_CS(r) \
CHOOSE_MODE(SC_CS((r)->mode.tt), REGS_CS((r)->mode.skas.regs))
CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
#define UPT_SS(r) \
CHOOSE_MODE(SC_SS((r)->mode.tt), REGS_SS((r)->mode.skas.regs))
CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
#define UPT_DS(r) \
CHOOSE_MODE(SC_DS((r)->mode.tt), REGS_DS((r)->mode.skas.regs))
CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
#define UPT_ES(r) \
CHOOSE_MODE(SC_ES((r)->mode.tt), REGS_ES((r)->mode.skas.regs))
CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
#define UPT_FS(r) \
CHOOSE_MODE(SC_FS((r)->mode.tt), REGS_FS((r)->mode.skas.regs))
CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
#define UPT_GS(r) \
CHOOSE_MODE(SC_GS((r)->mode.tt), REGS_GS((r)->mode.skas.regs))
#define UPT_SC(r) ((r)->mode.tt)
CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
extern int user_context(unsigned long sp);
#define UPT_IS_USER(r) \
CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user)
struct syscall_args {
unsigned long args[6];
};
#define SYSCALL_ARGS(r) ((struct syscall_args) \
{ .args = { UPT_SYSCALL_ARG1(r), \
UPT_SYSCALL_ARG2(r), \
UPT_SYSCALL_ARG3(r), \
UPT_SYSCALL_ARG4(r), \
UPT_SYSCALL_ARG5(r), \
UPT_SYSCALL_ARG6(r) } } )
#define UPT_REG(regs, reg) \
({ unsigned long val; \
......@@ -129,28 +158,26 @@ extern int mode_tt;
} while (0)
#define UPT_SET_SYSCALL_RETURN(r, res) \
CHOOSE_MODE(SC_SET_SYSCALL_RETURN((r)->mode.tt, (res)), \
REGS_SET_SYSCALL_RETURN((r)->mode.skas.regs, (res)))
CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \
REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res)))
#define UPT_RESTART_SYSCALL(r) \
CHOOSE_MODE(SC_RESTART_SYSCALL((r)->mode.tt), \
REGS_RESTART_SYSCALL((r)->mode.skas.regs))
CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \
REGS_RESTART_SYSCALL((r)->skas.regs))
#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
#define UPT_SYSCALL_NR(r) ((r)->syscall)
#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
#define UPT_SYSCALL_RET(r) UPT_EAX(r)
#define UPT_SEGV_IS_FIXABLE(r) \
CHOOSE_MODE(SC_SEGV_IS_FIXABLE(r->mode.tt), \
REGS_SEGV_IS_FIXABLE(&r->mode.skas))
CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
REGS_SEGV_IS_FIXABLE(&r->skas))
#define UPT_FAULT_ADDR(r) \
CHOOSE_MODE(SC_FAULT_ADDR(r->mode.tt), \
REGS_FAULT_ADDR(&r->mode.skas))
CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
#define UPT_FAULT_WRITE(r) \
CHOOSE_MODE(SC_FAULT_WRITE(r->mode.tt), \
REGS_FAULT_WRITE(&r->mode.skas))
CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
#endif
......
......@@ -33,34 +33,6 @@
#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
#ifdef CONFIG_MODE_TT
/* XXX struct sigcontext needs declaring by now */
static inline void sc_to_regs(struct uml_pt_regs *regs, struct sigcontext *sc,
unsigned long syscall)
{
regs->syscall = syscall;
regs->args[0] = SC_EBX(sc);
regs->args[1] = SC_ECX(sc);
regs->args[2] = SC_EDX(sc);
regs->args[3] = SC_ESI(sc);
regs->args[4] = SC_EDI(sc);
regs->args[5] = SC_EBP(sc);
}
#endif
#ifdef CONFIG_MODE_SKAS
static inline void host_to_regs(struct uml_pt_regs *regs)
{
regs->syscall = UPT_ORIG_EAX(regs);
regs->args[0] = UPT_EBX(regs);
regs->args[1] = UPT_ECX(regs);
regs->args[2] = UPT_EDX(regs);
regs->args[3] = UPT_ESI(regs);
regs->args[4] = UPT_EDI(regs);
regs->args[5] = UPT_EBP(regs);
}
#endif
extern unsigned long *sc_sigmask(void *sc_ptr);
extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
......
......@@ -4,10 +4,12 @@
*/
#include "asm/unistd.h"
#include "sysdep/ptrace.h"
typedef long syscall_handler_t(struct pt_regs);
#define EXECUTE_SYSCALL(syscall, regs) (*sys_call_table[syscall])(*regs);
#define EXECUTE_SYSCALL(syscall, regs) \
((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t old_mmap_i386;
......
/*
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __UML_UACCESS_H__
#define __UML_UACCESS_H__
extern int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher);
extern unsigned long __do_user_copy(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher,
void (*op)(void *to, const void *from,
int n), int *faulted_out);
void __do_copy(void *to, const void *from, int n);
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
......@@ -24,7 +24,7 @@ struct cpu_task {
extern struct cpu_task cpu_tasks[];
struct signal_info {
void (*handler)(int, struct uml_pt_regs *);
void (*handler)(int, union uml_pt_regs *);
int is_irq;
};
......@@ -87,7 +87,7 @@ extern void check_sigio(void);
extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
extern int arch_fixup(unsigned long address, void *sc_ptr);
extern void forward_pending_sigio(int target);
extern int can_do_skas(void);
......
......@@ -10,8 +10,8 @@ obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \
syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
time_kern.o tlb.o trap_kern.o trap_user.o um_arch.o \
umid.o user_util.o
time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
umid.o user_syms.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
......
......@@ -110,6 +110,7 @@ struct common_raw {
unsigned long sig;
unsigned long sr;
unsigned long sp;
struct arch_frame_data_raw arch;
};
#define SA_RESTORER (0x04000000)
......@@ -173,7 +174,6 @@ struct sc_frame_raw {
struct common_raw common;
unsigned long sc;
int restorer;
struct arch_frame_data_raw arch;
};
/* Changed only during early boot */
......@@ -185,7 +185,8 @@ static void sc_handler(int sig, struct sigcontext sc)
raw_sc->common.sr = frame_restorer();
raw_sc->common.sp = frame_sp();
raw_sc->sc = (unsigned long) ≻
setup_arch_frame_raw(&raw_sc->arch, &sc);
setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr);
os_stop_process(os_getpid());
kill(getpid(), SIGKILL);
}
......@@ -205,18 +206,25 @@ struct si_frame_raw {
struct common_raw common;
unsigned long sip;
unsigned long si;
unsigned long ucp;
unsigned long uc;
};
/* Changed only during early boot */
static struct si_frame_raw *raw_si = NULL;
static void si_handler(int sig, siginfo_t *si)
static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext)
{
raw_si->common.sig = (unsigned long) &sig;
raw_si->common.sr = frame_restorer();
raw_si->common.sp = frame_sp();
raw_si->sip = (unsigned long) &si;
raw_si->si = (unsigned long) si;
raw_si->ucp = (unsigned long) &ucontext;
raw_si->uc = (unsigned long) ucontext;
setup_arch_frame_raw(&raw_si->common.arch,
ucontext->uc_mcontext.fpregs, raw_si->common.sr);
os_stop_process(os_getpid());
kill(getpid(), SIGKILL);
}
......@@ -292,7 +300,7 @@ void capture_signal_stack(void)
&signal_frame_sc.common);
signal_frame_sc.sc_index = raw_sc.sc - base;
setup_arch_frame(&raw_sc.arch, &signal_frame_sc.arch);
setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch);
/* Ditto for the sigcontext, sigrestorer layout */
raw_sc.restorer = 1;
......@@ -300,6 +308,7 @@ void capture_signal_stack(void)
(void *) top, sigstack, PAGE_SIZE,
&signal_frame_sc_sr.common);
signal_frame_sc_sr.sc_index = raw_sc.sc - base;
setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch);
/* And the siginfo layout */
......@@ -308,6 +317,9 @@ void capture_signal_stack(void)
&signal_frame_si.common);
signal_frame_si.sip_index = raw_si.sip - base;
signal_frame_si.si_index = raw_si.si - base;
signal_frame_si.ucp_index = raw_si.ucp - base;
signal_frame_si.uc_index = raw_si.uc - base;
setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch);
if((munmap(stack, PAGE_SIZE) < 0) ||
(munmap(sigstack, PAGE_SIZE) < 0)){
......
......@@ -6,6 +6,8 @@
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "asm/signal.h"
#include "asm/uaccess.h"
#include "asm/ucontext.h"
#include "frame_kern.h"
#include "sigcontext.h"
#include "sysdep/ptrace.h"
......@@ -27,48 +29,62 @@ static int copy_restorer(void (*restorer)(void), unsigned long start,
sizeof(restorer)));
}
static int copy_sc_to_user(void *to, struct pt_regs *from)
static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from,
struct arch_frame_data *arch)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, from->regs.mode.tt,
&signal_frame_sc_sr.arch),
copy_sc_to_user_skas(to, &from->regs,
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
arch),
copy_sc_to_user_skas(to, fp, &from->regs,
current->thread.cr2,
current->thread.err)));
}
static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
unsigned long sp)
{
int err = 0;
err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs,
&signal_frame_si.common.arch);
err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
return(err);
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void),
struct pt_regs *regs, siginfo_t *info,
sigset_t *mask)
{
unsigned long start, sc, sigs;
void *sip;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
unsigned long start;
void *sip, *ucp, *fp;
start = stack_top - signal_frame_si.common.len -
sc_size(&signal_frame_sc.arch) - sig_size;
start = stack_top - signal_frame_si.common.len;
sip = (void *) (start + signal_frame_si.si_index);
sc = start + signal_frame_si.common.len;
sigs = sc + sc_size(&signal_frame_sc.arch);
ucp = (void *) (start + signal_frame_si.uc_index);
fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
if(restorer == NULL)
panic("setup_signal_stack_si - no restorer");
if(copy_sc_to_user((void *) sc, regs) ||
copy_to_user((void *) start, signal_frame_si.common.data,
if(copy_to_user((void *) start, signal_frame_si.common.data,
signal_frame_si.common.len) ||
copy_to_user((void *) (start + signal_frame_si.common.sig_index),
&sig, sizeof(sig)) ||
copy_siginfo_to_user(sip, info) ||
copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
sizeof(sip)) ||
copy_to_user((void *) sigs, mask, sig_size) ||
copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
sizeof(ucp)) ||
copy_restorer(restorer, start, signal_frame_si.common.sr_index,
signal_frame_si.common.sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
PT_REGS_SP(regs) = start + signal_frame_sc.common.sp_index;
PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
return(0);
}
......@@ -96,7 +112,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if(copy_to_user((void *) start, frame->data, frame->len) ||
copy_to_user((void *) (start + frame->sig_index), &sig,
sizeof(sig)) ||
copy_sc_to_user(user_sc, regs) ||
copy_sc_to_user(user_sc, NULL, regs,
&signal_frame_sc.common.arch) ||
copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
......
......@@ -271,7 +271,7 @@ void enable_irq(unsigned int irq)
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
{
/*
* 0 return value means that this irq is already being
......
......@@ -42,7 +42,7 @@ static int pollfds_size = 0;
extern int io_count, intr_count;
void sigio_handler(int sig, struct uml_pt_regs *regs)
void sigio_handler(int sig, union uml_pt_regs *regs)
{
struct irq_fd *irq_fd, *next;
int i, n;
......
......@@ -27,6 +27,7 @@
#include "init.h"
#include "os.h"
#include "mode_kern.h"
#include "uml_uaccess.h"
/* Changed during early boot */
pgd_t swapper_pg_dir[1024];
......@@ -414,8 +415,28 @@ __uml_setup("mem=", uml_mem_setup,
struct page *arch_validate(struct page *page, int mask, int order)
{
return(CHOOSE_MODE_PROC(arch_validate_tt, arch_validate_skas, page,
mask, order));
unsigned long addr, zero = 0;
int i;
again:
if(page == NULL) return(page);
if(PageHighMem(page)) return(page);
addr = (unsigned long) page_address(page);
for(i = 0; i < (1 << order); i++){
current->thread.fault_addr = (void *) addr;
if(__do_copy_to_user((void *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
&current->thread.fault_catcher)){
if(!(mask & __GFP_WAIT)) return(NULL);
else break;
}
addr += PAGE_SIZE;
}
if(i == (1 << order)) return(page);
page = _alloc_pages(mask, order);
goto again;
}
DECLARE_MUTEX(vm_reserved_sem);
......
......@@ -169,8 +169,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
void initial_thread_cb(void (*proc)(void *), void *arg)
{
int save_kmalloc_ok = kmalloc_ok;
kmalloc_ok = 0;
CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
arg);
kmalloc_ok = save_kmalloc_ok;
}
unsigned long stack_sp(unsigned long page)
......
......@@ -18,6 +18,7 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
#include "user_util.h"
#include "asm/ucontext.h"
#include "kern_util.h"
#include "signal_kern.h"
#include "signal_user.h"
......@@ -237,20 +238,20 @@ int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
}
}
static int copy_sc_from_user(struct pt_regs *to, void *from)
static int copy_sc_from_user(struct pt_regs *to, void *from,
struct arch_frame_data *arch)
{
int ret;
ret = CHOOSE_MODE(copy_sc_from_user_tt(to->regs.mode.tt, from,
&signal_frame_sc.arch),
ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
copy_sc_from_user_skas(&to->regs, from));
return(ret);
}
int sys_sigreturn(struct pt_regs regs)
{
void *sc = sp_to_sc(PT_REGS_SP(&regs));
void *mask = sp_to_mask(PT_REGS_SP(&regs));
void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
spin_lock_irq(&current->sig->siglock);
......@@ -260,22 +261,25 @@ int sys_sigreturn(struct pt_regs regs)
sigdelsetmask(&current->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
copy_sc_from_user(&current->thread.regs, sc);
copy_sc_from_user(&current->thread.regs, sc,
&signal_frame_sc.common.arch);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
int sys_rt_sigreturn(struct pt_regs regs)
{
void *sc = sp_to_rt_sc(PT_REGS_SP(&regs));
void *mask = sp_to_rt_mask(PT_REGS_SP(&regs));
struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
void *fp;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
spin_lock_irq(&current->sig->siglock);
copy_from_user(&current->blocked, mask, sig_size);
copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
sigdelsetmask(&current->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
copy_sc_from_user(&current->thread.regs, sc);
fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
&signal_frame_si.common.arch);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
......
......@@ -12,10 +12,11 @@ extern unsigned long exec_fpx_regs[];
extern int have_fpx_regs;
extern void user_time_init_skas(void);
extern int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr);
extern int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr);
extern int copy_sc_to_user_skas(void *to_ptr, void *fp,
union uml_pt_regs *regs,
unsigned long fault_addr, int fault_type);
extern void sig_handler_common_skas(int sig, struct sigcontext *sc);
extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void halt_skas(void);
extern void reboot_skas(void);
extern void kill_off_processes_skas(void);
......
......@@ -32,11 +32,10 @@ extern void before_mem_skas(unsigned long unused);
extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
unsigned long *task_size_out);
extern int start_uml_skas(void);
extern struct page *arch_validate_skas(struct page *page, int mask, int order);
extern int external_pid_skas(struct task_struct *task);
extern int thread_pid_skas(struct task_struct *task);
#define kmem_end_skas (host_task_size)
#define kmem_end_skas (host_task_size - 1024 * 1024)
#endif
......
......@@ -17,21 +17,21 @@ extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
extern int start_idle_thread(void *stack, void *switch_buf_ptr,
void **fork_buf_ptr);
extern int user_thread(unsigned long stack, int flags);
extern void userspace(struct uml_pt_regs *regs);
extern void userspace(union uml_pt_regs *regs);
extern void new_thread_proc(void *stack, void (*handler)(int sig));
extern void remove_sigstack(void);
extern void new_thread_handler(int sig);
extern void handle_syscall(struct uml_pt_regs *regs);
extern void handle_syscall(union uml_pt_regs *regs);
extern void map(int fd, unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
extern int unmap(int fd, void *addr, int len);
extern int protect(int fd, unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern void user_signal(int sig, struct uml_pt_regs *regs);
extern void user_signal(int sig, union uml_pt_regs *regs);
extern int singlestepping_skas(void);
extern int new_mm(int from);
extern void save_registers(struct uml_pt_regs *regs);
extern void restore_registers(struct uml_pt_regs *regs);
extern void save_registers(union uml_pt_regs *regs);
extern void restore_registers(union uml_pt_regs *regs);
extern void start_userspace(void);
extern void init_registers(int pid);
......
......@@ -18,11 +18,6 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
}
struct page *arch_validate_skas(struct page *page, int mask, int order)
{
return(page);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -20,10 +20,10 @@
#include "user_util.h"
#include "kern_util.h"
#include "skas.h"
#include "skas_ptrace.h"
#include "sysdep/sigcontext.h"
#include "os.h"
#include "proc_mm.h"
#include "skas_ptrace.h"
unsigned long exec_regs[FRAME_SIZE];
unsigned long exec_fp_regs[HOST_FP_SIZE];
......@@ -42,11 +42,11 @@ static void handle_segv(int pid)
segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
}
static void handle_trap(int pid, struct uml_pt_regs *regs)
static void handle_trap(int pid, union uml_pt_regs *regs)
{
int err, syscall_nr, status;
syscall_nr = PT_SYSCALL_NR(regs->mode.skas.regs);
syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
if(syscall_nr < 1){
relay_signal(SIGTRAP, regs);
return;
......@@ -115,7 +115,7 @@ void start_userspace(void)
userspace_pid = pid;
}
void userspace(struct uml_pt_regs *regs)
void userspace(union uml_pt_regs *regs)
{
int err, status, op;
......@@ -131,7 +131,7 @@ void userspace(struct uml_pt_regs *regs)
panic("userspace - waitpid failed, errno = %d\n",
errno);
regs->is_user = 1;
regs->skas.is_user = 1;
save_registers(regs);
if(WIFSTOPPED(status)){
......@@ -191,28 +191,28 @@ void thread_wait(void *sw, void *fb)
longjmp(*fork_buf, 1);
}
static int move_registers(int int_op, int fp_op, struct uml_pt_regs *regs,
static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs,
unsigned long *fp_regs)
{
if(ptrace(int_op, userspace_pid, 0, regs->mode.skas.regs) < 0)
if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0)
return(-errno);
if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
return(-errno);
return(0);
}
void save_registers(struct uml_pt_regs *regs)
void save_registers(union uml_pt_regs *regs)
{
unsigned long *fp_regs;
int err, fp_op;
if(have_fpx_regs){
fp_op = PTRACE_GETFPXREGS;
fp_regs = regs->mode.skas.xfp;
fp_regs = regs->skas.xfp;
}
else {
fp_op = PTRACE_GETFPREGS;
fp_regs = regs->mode.skas.fp;
fp_regs = regs->skas.fp;
}
err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
......@@ -221,18 +221,18 @@ void save_registers(struct uml_pt_regs *regs)
err);
}
void restore_registers(struct uml_pt_regs *regs)
void restore_registers(union uml_pt_regs *regs)
{
unsigned long *fp_regs;
int err, fp_op;
if(have_fpx_regs){
fp_op = PTRACE_SETFPXREGS;
fp_regs = regs->mode.skas.xfp;
fp_regs = regs->skas.xfp;
}
else {
fp_op = PTRACE_SETFPREGS;
fp_regs = regs->mode.skas.fp;
fp_regs = regs->skas.fp;
}
err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
......@@ -272,10 +272,14 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
(*cb_proc)(cb_arg);
longjmp(*cb_back, 1);
}
else if(n == 3)
else if(n == 3){
kmalloc_ok = 0;
return(0);
else if(n == 4)
}
else if(n == 4){
kmalloc_ok = 0;
return(1);
}
longjmp(**switch_buf, 1);
}
......@@ -296,8 +300,11 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_proc = proc;
cb_arg = arg;
cb_back = &here;
block_signals();
if(setjmp(here) == 0)
longjmp(initial_jmpbuf, 2);
unblock_signals();
cb_proc = NULL;
cb_arg = NULL;
......
......@@ -68,8 +68,7 @@ void new_thread_handler(int sig)
n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
if(n == 1)
userspace(&current->thread.regs.regs);
else if(n == 2)
do_exit(0);
else do_exit(0);
}
void new_thread_proc(void *stack, void (*handler)(int sig))
......@@ -109,21 +108,21 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
void (*handler)(int);
if(current->thread.forking){
memcpy(&p->thread.regs.regs.mode.skas,
&current->thread.regs.regs.mode.skas,
sizeof(p->thread.regs.regs.mode.skas));
REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.mode.skas.regs, 0);
if(sp != 0) REGS_SP(p->thread.regs.regs.mode.skas.regs) = sp;
memcpy(&p->thread.regs.regs.skas,
&current->thread.regs.regs.skas,
sizeof(p->thread.regs.regs.skas));
REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
handler = fork_handler;
}
else {
memcpy(p->thread.regs.regs.mode.skas.regs, exec_regs,
sizeof(p->thread.regs.regs.mode.skas.regs));
memcpy(p->thread.regs.regs.mode.skas.fp, exec_fp_regs,
sizeof(p->thread.regs.regs.mode.skas.fp));
memcpy(p->thread.regs.regs.mode.skas.xfp, exec_fpx_regs,
sizeof(p->thread.regs.regs.mode.skas.xfp));
memcpy(p->thread.regs.regs.skas.regs, exec_regs,
sizeof(p->thread.regs.regs.skas.regs));
memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs,
sizeof(p->thread.regs.regs.skas.fp));
memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs,
sizeof(p->thread.regs.regs.skas.xfp));
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
......
......@@ -15,7 +15,7 @@
extern int userspace_pid;
int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr)
int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
{
struct sigcontext sc, *from = from_ptr;
unsigned long fpregs[FP_FRAME_SIZE];
......@@ -26,26 +26,26 @@ int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr)
if(err)
return(err);
regs->mode.skas.regs[GS] = sc.gs;
regs->mode.skas.regs[FS] = sc.fs;
regs->mode.skas.regs[ES] = sc.es;
regs->mode.skas.regs[DS] = sc.ds;
regs->mode.skas.regs[EDI] = sc.edi;
regs->mode.skas.regs[ESI] = sc.esi;
regs->mode.skas.regs[EBP] = sc.ebp;
regs->mode.skas.regs[UESP] = sc.esp;
regs->mode.skas.regs[EBX] = sc.ebx;
regs->mode.skas.regs[EDX] = sc.edx;
regs->mode.skas.regs[ECX] = sc.ecx;
regs->mode.skas.regs[EAX] = sc.eax;
regs->mode.skas.regs[EIP] = sc.eip;
regs->mode.skas.regs[CS] = sc.cs;
regs->mode.skas.regs[EFL] = sc.eflags;
regs->mode.skas.regs[UESP] = sc.esp_at_signal;
regs->mode.skas.regs[SS] = sc.ss;
regs->mode.skas.fault_addr = sc.cr2;
regs->mode.skas.fault_type = FAULT_WRITE(sc.err);
regs->mode.skas.trap_type = sc.trapno;
regs->skas.regs[GS] = sc.gs;
regs->skas.regs[FS] = sc.fs;
regs->skas.regs[ES] = sc.es;
regs->skas.regs[DS] = sc.ds;
regs->skas.regs[EDI] = sc.edi;
regs->skas.regs[ESI] = sc.esi;
regs->skas.regs[EBP] = sc.ebp;
regs->skas.regs[UESP] = sc.esp;
regs->skas.regs[EBX] = sc.ebx;
regs->skas.regs[EDX] = sc.edx;
regs->skas.regs[ECX] = sc.ecx;
regs->skas.regs[EAX] = sc.eax;
regs->skas.regs[EIP] = sc.eip;
regs->skas.regs[CS] = sc.cs;
regs->skas.regs[EFL] = sc.eflags;
regs->skas.regs[UESP] = sc.esp_at_signal;
regs->skas.regs[SS] = sc.ss;
regs->skas.fault_addr = sc.cr2;
regs->skas.fault_type = FAULT_WRITE(sc.err);
regs->skas.trap_type = sc.trapno;
err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
if(err < 0){
......@@ -57,7 +57,7 @@ int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr)
return(0);
}
int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs,
unsigned long fault_addr, int fault_type)
{
struct sigcontext sc, *to = to_ptr;
......@@ -65,26 +65,26 @@ int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
unsigned long fpregs[FP_FRAME_SIZE];
int err;
sc.gs = regs->mode.skas.regs[GS];
sc.fs = regs->mode.skas.regs[FS];
sc.es = regs->mode.skas.regs[ES];
sc.ds = regs->mode.skas.regs[DS];
sc.edi = regs->mode.skas.regs[EDI];
sc.esi = regs->mode.skas.regs[ESI];
sc.ebp = regs->mode.skas.regs[EBP];
sc.esp = regs->mode.skas.regs[UESP];
sc.ebx = regs->mode.skas.regs[EBX];
sc.edx = regs->mode.skas.regs[EDX];
sc.ecx = regs->mode.skas.regs[ECX];
sc.eax = regs->mode.skas.regs[EAX];
sc.eip = regs->mode.skas.regs[EIP];
sc.cs = regs->mode.skas.regs[CS];
sc.eflags = regs->mode.skas.regs[EFL];
sc.esp_at_signal = regs->mode.skas.regs[UESP];
sc.ss = regs->mode.skas.regs[SS];
sc.gs = regs->skas.regs[GS];
sc.fs = regs->skas.regs[FS];
sc.es = regs->skas.regs[ES];
sc.ds = regs->skas.regs[DS];
sc.edi = regs->skas.regs[EDI];
sc.esi = regs->skas.regs[ESI];
sc.ebp = regs->skas.regs[EBP];
sc.esp = regs->skas.regs[UESP];
sc.ebx = regs->skas.regs[EBX];
sc.edx = regs->skas.regs[EDX];
sc.ecx = regs->skas.regs[ECX];
sc.eax = regs->skas.regs[EAX];
sc.eip = regs->skas.regs[EIP];
sc.cs = regs->skas.regs[CS];
sc.eflags = regs->skas.regs[EFL];
sc.esp_at_signal = regs->skas.regs[UESP];
sc.ss = regs->skas.regs[SS];
sc.cr2 = fault_addr;
sc.err = TO_SC_ERR(fault_type);
sc.trapno = regs->mode.skas.trap_type;
sc.trapno = regs->skas.trap_type;
err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
if(err < 0){
......@@ -92,7 +92,8 @@ int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
"errno = %d\n", errno);
return(1);
}
to_fp = (struct _fpstate *)((unsigned long) to + sizeof(*to));
to_fp = (struct _fpstate *)
(fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
sc.fpstate = to_fp;
if(err)
......
......@@ -21,7 +21,7 @@ long execute_syscall_skas(void *r)
current->thread.nsyscalls++;
nsyscalls++;
syscall = regs->regs.syscall;
syscall = UPT_SYSCALL_NR(&regs->regs);
if((syscall >= NR_syscalls) || (syscall < 0))
res = -ENOSYS;
......
......@@ -15,18 +15,17 @@
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
void handle_syscall(struct uml_pt_regs *regs)
void handle_syscall(union uml_pt_regs *regs)
{
long result;
int index;
host_to_regs(regs);
index = record_syscall_start(UPT_SYSCALL_NR(regs));
syscall_trace();
result = execute_syscall(regs);
REGS_SET_SYSCALL_RETURN(regs->mode.skas.regs, result);
REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
(result == -ERESTARTNOINTR))
do_signal(result);
......
......@@ -134,9 +134,8 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
void flush_tlb_mm_skas(struct mm_struct *mm)
{
if(mm == NULL)
flush_tlb_kernel_vm_skas();
else fix_range(mm, 0, host_task_size, 0);
flush_tlb_kernel_vm_skas();
fix_range(mm, 0, host_task_size, 0);
}
void force_flush_all_skas(void)
......
......@@ -13,41 +13,40 @@
#include "task.h"
#include "sigcontext.h"
void sig_handler_common_skas(int sig, struct sigcontext *sc)
void sig_handler_common_skas(int sig, void *sc_ptr)
{
struct uml_pt_regs save_regs, *r;
struct sigcontext *sc = sc_ptr;
struct skas_regs *r;
struct signal_info *info;
int save_errno = errno;
r = (struct uml_pt_regs *) TASK_REGS(get_current());
save_regs = *r;
r = &TASK_REGS(get_current())->skas;
r->is_user = 0;
r->mode.skas.fault_addr = SC_FAULT_ADDR(sc);
r->mode.skas.fault_type = SC_FAULT_TYPE(sc);
r->mode.skas.trap_type = SC_TRAP_TYPE(sc);
r->fault_addr = SC_FAULT_ADDR(sc);
r->fault_type = SC_FAULT_TYPE(sc);
r->trap_type = SC_TRAP_TYPE(sc);
change_sig(SIGUSR1, 1);
info = &sig_info[sig];
if(!info->is_irq) unblock_signals();
(*info->handler)(sig, r);
(*info->handler)(sig, (union uml_pt_regs *) r);
*r = save_regs;
errno = save_errno;
}
extern int missed_ticks[];
void user_signal(int sig, struct uml_pt_regs *regs)
void user_signal(int sig, union uml_pt_regs *regs)
{
struct signal_info *info;
if(sig == SIGVTALRM)
missed_ticks[cpu()]++;
regs->is_user = 1;
regs->mode.skas.fault_addr = 0;
regs->mode.skas.fault_type = 0;
regs->mode.skas.trap_type = 0;
regs->skas.is_user = 1;
regs->fault_addr = 0;
regs->skas.fault_type = 0;
regs->skas.trap_type = 0;
info = &sig_info[sig];
(*info->handler)(sig, regs);
......
......@@ -37,7 +37,7 @@ int timer_irq_inited = 0;
*/
int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
void timer_irq(struct uml_pt_regs *regs)
void timer_irq(union uml_pt_regs *regs)
{
int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
......@@ -50,7 +50,9 @@ void boot_timer_handler(int sig)
{
struct pt_regs regs;
regs.regs.is_user = 0;
CHOOSE_MODE((void)
(UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
(void) (regs.regs.skas.is_user = 0));
do_timer(&regs);
}
......@@ -118,7 +120,7 @@ void __const_udelay(um_udelay_t usecs)
for(i=0;i<n;i++) ;
}
void timer_handler(int sig, struct uml_pt_regs *regs)
void timer_handler(int sig, union uml_pt_regs *regs)
{
#ifdef CONFIG_SMP
update_process_times(user_context(UPT_SP(regs)));
......
......@@ -164,14 +164,15 @@ void bad_segv(unsigned long address, unsigned long ip, int is_write)
force_sig_info(SIGSEGV, &si, current);
}
void relay_signal(int sig, struct uml_pt_regs *regs)
void relay_signal(int sig, union uml_pt_regs *regs)
{
if(arch_handle_signal(sig, regs)) return;
if(!regs->is_user) panic("Kernel mode signal %d", sig);
if(!UPT_IS_USER(regs))
panic("Kernel mode signal %d", sig);
force_sig(sig, current);
}
void bus_handler(int sig, struct uml_pt_regs *regs)
void bus_handler(int sig, union uml_pt_regs *regs)
{
if(current->thread.fault_catcher != NULL)
do_longjmp(current->thread.fault_catcher, 1);
......
......@@ -48,11 +48,11 @@ struct {
int is_user;
} segfault_record[1024];
void segv_handler(int sig, struct uml_pt_regs *regs)
void segv_handler(int sig, union uml_pt_regs *regs)
{
int index, max;
if(regs->is_user && !UPT_SEGV_IS_FIXABLE(regs)){
if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){
bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs),
UPT_FAULT_WRITE(regs));
return;
......@@ -65,35 +65,35 @@ void segv_handler(int sig, struct uml_pt_regs *regs)
segfault_record[index].pid = os_getpid();
segfault_record[index].is_write = UPT_FAULT_WRITE(regs);
segfault_record[index].sp = UPT_SP(regs);
segfault_record[index].is_user = regs->is_user;
segfault_record[index].is_user = UPT_IS_USER(regs);
segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs),
regs->is_user, regs);
UPT_IS_USER(regs), regs);
}
void usr2_handler(int sig, struct uml_pt_regs *regs)
void usr2_handler(int sig, union uml_pt_regs *regs)
{
CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
}
struct signal_info sig_info[] = {
[ SIGTRAP ] { handler : relay_signal,
is_irq : 0 },
[ SIGFPE ] { handler : relay_signal,
is_irq : 0 },
[ SIGILL ] { handler : relay_signal,
is_irq : 0 },
[ SIGBUS ] { handler : bus_handler,
is_irq : 0 },
[ SIGSEGV] { handler : segv_handler,
is_irq : 0 },
[ SIGIO ] { handler : sigio_handler,
is_irq : 1 },
[ SIGVTALRM ] { handler : timer_handler,
is_irq : 1 },
[ SIGALRM ] { handler : timer_handler,
is_irq : 1 },
[ SIGUSR2 ] { handler : usr2_handler,
is_irq : 0 },
[ SIGTRAP ] { .handler = relay_signal,
.is_irq = 0 },
[ SIGFPE ] { .handler = relay_signal,
.is_irq = 0 },
[ SIGILL ] { .handler = relay_signal,
.is_irq = 0 },
[ SIGBUS ] { .handler = bus_handler,
.is_irq = 0 },
[ SIGSEGV] { .handler = segv_handler,
.is_irq = 0 },
[ SIGIO ] { .handler = sigio_handler,
.is_irq = 1 },
[ SIGVTALRM ] { .handler = timer_handler,
.is_irq = 1 },
[ SIGALRM ] { .handler = timer_handler,
.is_irq = 1 },
[ SIGUSR2 ] { .handler = usr2_handler,
.is_irq = 0 },
};
void sig_handler(int sig, struct sigcontext sc)
......
......@@ -74,16 +74,16 @@ static void *xterm_data;
static int xterm_fd;
extern void *xterm_init(char *, int, struct chan_opts *);
extern int xterm_open(int, int, int, void *);
extern int xterm_open(int, int, int, void *, char **);
extern void xterm_close(int, void *);
int open_gdb_chan(void)
{
char stack[UM_KERN_PAGE_SIZE];
char stack[UM_KERN_PAGE_SIZE], *dummy;
opts.tramp_stack = (unsigned long) stack;
xterm_data = xterm_init("", 0, &opts);
xterm_fd = xterm_open(1, 1, 1, xterm_data);
xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy);
return(xterm_fd);
}
......
......@@ -13,9 +13,10 @@ extern int tracing_pid;
extern int tracer(int (*init_proc)(void *), void *sp);
extern void user_time_init_tt(void);
extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
extern int copy_sc_to_user_tt(void *to_ptr, void *from_ptr, void *data);
extern void sig_handler_common_tt(int sig, struct sigcontext *sc);
extern void syscall_handler_tt(int sig, struct uml_pt_regs *regs);
extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr,
void *data);
extern void sig_handler_common_tt(int sig, void *sc);
extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
extern void reboot_tt(void);
extern void halt_tt(void);
extern int is_tracer_winch(int pid, int fd, void *data);
......
......@@ -33,7 +33,6 @@ extern void before_mem_tt(unsigned long brk_start);
extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
unsigned long *task_size_out);
extern int start_uml_tt(void);
extern struct page *arch_validate_tt(struct page *page, int mask, int order);
extern int external_pid_tt(struct task_struct *task);
extern int thread_pid_tt(struct task_struct *task);
......
......@@ -26,10 +26,11 @@ extern void set_tracing(void *t, int tracing);
extern int is_tracing(void *task);
extern int singlestepping_tt(void *t);
extern void clear_singlestep(void *t);
extern void syscall_handler(int sig, struct uml_pt_regs *regs);
extern void syscall_handler(int sig, union uml_pt_regs *regs);
extern void exit_kernel(int pid, void *task);
extern int do_syscall(void *task, int pid);
extern int is_valid_pid(int pid);
extern void remap_data(void *segment_start, void *segment_end, int w);
#endif
......
......@@ -12,6 +12,7 @@
#include "asm/errno.h"
#include "asm/current.h"
#include "asm/a.out.h"
#include "uml_uaccess.h"
#define ABOVE_KMEM (16 * 1024 * 1024)
......@@ -51,9 +52,6 @@ static inline int copy_from_user_tt(void *to, const void *from, int n)
&current->thread.fault_catcher) : n);
}
extern int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher);
static inline int copy_to_user_tt(void *to, const void *from, int n)
{
return(access_ok_tt(VERIFY_WRITE, to, n) ?
......
......@@ -39,32 +39,6 @@ unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
return(START);
}
struct page *arch_validate_tt(struct page *page, int mask, int order)
{
unsigned long addr, zero = 0;
int i;
again:
if(page == NULL) return(page);
if(PageHighMem(page)) return(page);
addr = (unsigned long) page_address(page);
for(i = 0; i < (1 << order); i++){
current->thread.fault_addr = (void *) addr;
if(__do_copy_to_user((void *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
&current->thread.fault_catcher)){
if(!(mask & __GFP_WAIT)) return(NULL);
else break;
}
addr += PAGE_SIZE;
}
if(i == (1 << order)) return(page);
page = alloc_pages(mask, order);
goto again;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -111,8 +111,6 @@ void exit_thread_tt(void)
close(current->thread.mode.tt.switch_pipe[1]);
}
extern void schedule_tail(struct task_struct *prev);
static void new_thread_handler(int sig)
{
int (*fn)(void *);
......@@ -120,7 +118,7 @@ static void new_thread_handler(int sig)
fn = current->thread.request.u.thread.proc;
arg = current->thread.request.u.thread.arg;
current->thread.regs.regs.mode.tt = (void *) (&sig + 1);
UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
block_signals();
......@@ -160,7 +158,7 @@ static int new_thread_proc(void *stack)
void finish_fork_handler(int sig)
{
current->thread.regs.regs.mode.tt = (void *) (&sig + 1);
UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
#ifdef CONFIG_SMP
......@@ -168,6 +166,7 @@ void finish_fork_handler(int sig)
#endif
enable_timer();
change_sig(SIGVTALRM, 1);
sti();
force_flush_all();
if(current->mm != current->parent->mm)
protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
......@@ -187,6 +186,7 @@ int fork_tramp(void *stack)
{
int sig = sigusr1;
cli();
init_new_thread_stack(stack, finish_fork_handler);
kill(os_getpid(), sig);
......@@ -232,10 +232,10 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
}
if(current->thread.forking){
sc_to_sc(p->thread.regs.regs.mode.tt,
current->thread.regs.regs.mode.tt);
SC_SET_SYSCALL_RETURN(p->thread.regs.regs.mode.tt, 0);
if(sp != 0) SC_SP(p->thread.regs.regs.mode.tt) = sp;
sc_to_sc(UPT_SC(&p->thread.regs.regs),
UPT_SC(&current->thread.regs.regs));
SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
}
p->thread.mode.tt.extern_pid = new_pid;
......
......@@ -29,14 +29,15 @@ int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data)
return(err);
}
int copy_sc_to_user_tt(void *to_ptr, void *from_ptr, void *data)
int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data)
{
struct arch_frame_data *arch = data;
struct sigcontext *to = to_ptr, *from = from_ptr;
struct _fpstate *to_fp, *from_fp;
int err;
to_fp = (struct _fpstate *)((unsigned long) to + sizeof(*to));
to_fp = (struct _fpstate *)
(fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
from_fp = from->fpstate;
err = copy_to_user_proc(to, from, sizeof(*to));
if(from_fp != NULL){
......
......@@ -20,29 +20,32 @@ static inline int check_area(void *ptr, int size)
static int check_readlink(struct pt_regs *regs)
{
return(check_area((void *) regs->regs.args[1], regs->regs.args[2]));
return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
UPT_SYSCALL_ARG2(&regs->regs)));
}
static int check_utime(struct pt_regs *regs)
{
return(check_area((void *) regs->regs.args[1],
return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
sizeof(struct utimbuf)));
}
static int check_oldstat(struct pt_regs *regs)
{
return(check_area((void *) regs->regs.args[1],
return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
sizeof(struct __old_kernel_stat)));
}
static int check_stat(struct pt_regs *regs)
{
return(check_area((void *) regs->regs.args[1], sizeof(struct stat)));
return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
sizeof(struct stat)));
}
static int check_stat64(struct pt_regs *regs)
{
return(check_area((void *) regs->regs.args[1], sizeof(struct stat64)));
return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
sizeof(struct stat64)));
}
struct bogus {
......@@ -90,7 +93,7 @@ struct bogus this_is_bogus[256] = {
static int check_bogosity(struct pt_regs *regs)
{
struct bogus *bogon = &this_is_bogus[regs->regs.syscall];
struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(&regs->regs)];
if(!bogon->kernel_ds) return(0);
if(bogon->check_params && (*bogon->check_params)(regs))
......@@ -109,7 +112,7 @@ long execute_syscall_tt(void *r)
current->thread.nsyscalls++;
nsyscalls++;
syscall = regs->regs.syscall;
syscall = UPT_SYSCALL_NR(&regs->regs);
if((syscall >= NR_syscalls) || (syscall < 0))
res = -ENOSYS;
......
......@@ -22,15 +22,14 @@
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
void syscall_handler_tt(int sig, struct uml_pt_regs *regs)
void syscall_handler_tt(int sig, union uml_pt_regs *regs)
{
void *sc;
long result;
int index, syscall;
syscall = regs->syscall;
sc = regs->mode.tt;
sc_to_regs(regs, sc, syscall);
syscall = UPT_SYSCALL_NR(regs);
sc = UPT_SC(regs);
SC_START_SYSCALL(sc);
index = record_syscall_start(syscall);
......@@ -40,7 +39,7 @@ void syscall_handler_tt(int sig, struct uml_pt_regs *regs)
/* regs->sc may have changed while the system call ran (there may
* have been an interrupt or segfault), so it needs to be refreshed.
*/
regs->mode.tt = sc;
UPT_SC(regs) = sc;
SC_SET_SYSCALL_RETURN(sc, result);
if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
......@@ -54,7 +53,7 @@ void syscall_handler_tt(int sig, struct uml_pt_regs *regs)
int do_syscall(void *task, int pid)
{
unsigned long proc_regs[FRAME_SIZE];
struct uml_pt_regs *regs;
union uml_pt_regs *regs;
int syscall;
if(ptrace_getregs(pid, proc_regs) < 0)
......
......@@ -14,26 +14,27 @@
#include "task.h"
#include "tt.h"
void sig_handler_common_tt(int sig, struct sigcontext *sc)
void sig_handler_common_tt(int sig, void *sc_ptr)
{
struct uml_pt_regs save_regs, *r;
struct sigcontext *sc = sc_ptr;
struct tt_regs save_regs, *r;
struct signal_info *info;
int save_errno = errno, is_user;
unprotect_kernel_mem();
r = (struct uml_pt_regs *) TASK_REGS(get_current());
r = &TASK_REGS(get_current())->tt;
save_regs = *r;
is_user = user_context(SC_SP(sc));
r->is_user = is_user;
r->mode.tt = sc;
if(sig != SIGUSR2) r->syscall = -1;
r->sc = sc;
if(sig != SIGUSR2)
r->syscall = -1;
change_sig(SIGUSR1, 1);
info = &sig_info[sig];
if(!info->is_irq) unblock_signals();
(*info->handler)(sig, r);
(*info->handler)(sig, (union uml_pt_regs *) r);
if(is_user){
interrupt_end();
......
......@@ -7,34 +7,7 @@
#include <setjmp.h>
#include <string.h>
#include "user_util.h"
static unsigned long __do_user_copy(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher,
void (*op)(void *to, const void *from,
int n), int *faulted_out)
{
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
jmp_buf jbuf;
*fault_catcher = &jbuf;
if(setjmp(jbuf) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
}
else {
ret = *faddrp;
*faulted_out = 1;
}
*fault_addr = NULL;
*fault_catcher = NULL;
return ret;
}
static void __do_copy(void *to, const void *from, int n)
{
memcpy(to, from, n);
}
#include "uml_uaccess.h"
int __do_copy_from_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher)
......@@ -48,19 +21,6 @@ int __do_copy_from_user(void *to, const void *from, int n,
else return(n - (fault - (unsigned long) from));
}
int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher)
{
unsigned long fault;
int faulted;
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
if(!faulted) return(0);
else return(n - (fault - (unsigned long) to));
}
static void __do_strncpy(void *dst, const void *src, int count)
{
strncpy(dst, src, count);
......
/*
* Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <setjmp.h>
#include <string.h>
/* These are here rather than tt/uaccess.c because skas mode needs them in
* order to do SIGBUS recovery when a tmpfs mount runs out of room.
*/
unsigned long __do_user_copy(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher,
void (*op)(void *to, const void *from,
int n), int *faulted_out)
{
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
jmp_buf jbuf;
*fault_catcher = &jbuf;
if(setjmp(jbuf) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
}
else {
ret = *faddrp;
*faulted_out = 1;
}
*fault_addr = NULL;
*fault_catcher = NULL;
return ret;
}
void __do_copy(void *to, const void *from, int n)
{
memcpy(to, from, n);
}
int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher)
{
unsigned long fault;
int faulted;
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
if(!faulted) return(0);
else return(n - (fault - (unsigned long) to));
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
......@@ -117,7 +117,7 @@ void arch_check_bugs(void)
if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
}
int arch_handle_signal(int sig, struct uml_pt_regs *regs)
int arch_handle_signal(int sig, union uml_pt_regs *regs)
{
unsigned long ip;
......
......@@ -21,7 +21,7 @@ int sc_size(void *data)
void sc_to_sc(void *to_ptr, void *from_ptr)
{
struct sigcontext *to = to_ptr, *from = from_ptr;
int size = sizeof(*to) + signal_frame_sc.arch.fpstate_size;
int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size;
memcpy(to, from, size);
if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1);
......
......@@ -9,7 +9,7 @@ extern void print_tail(void);
int main(int argc, char **argv)
{
print_head();
print_ptr("TASK_REGS", "struct uml_pt_regs",
print_ptr("TASK_REGS", "union uml_pt_regs",
offsetof(struct task_struct, thread.regs));
print("TASK_PID", "int", offsetof(struct task_struct, pid));
print_tail();
......
......@@ -48,7 +48,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
/* fake once used fs and gs selectors? */ \
pr_reg[9] = PT_REGS_DS(regs); \
pr_reg[10] = PT_REGS_DS(regs); \
pr_reg[11] = regs->regs.syscall; \
pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \
pr_reg[12] = PT_REGS_IP(regs); \
pr_reg[13] = PT_REGS_CS(regs); \
pr_reg[14] = PT_REGS_EFLAGS(regs); \
......
......@@ -9,7 +9,7 @@
#ifndef __ASSEMBLY__
#include "linux/config.h"
#include "skas_ptrace.h"
#include "asm/current.h"
#define pt_regs pt_regs_subarch
......@@ -23,9 +23,10 @@
#undef instruction_pointer
#include "sysdep/ptrace.h"
#include "skas_ptrace.h"
struct pt_regs {
struct uml_pt_regs regs;
union uml_pt_regs regs;
};
#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS }
......
......@@ -6,6 +6,7 @@
#ifndef __UM_PTRACE_I386_H
#define __UM_PTRACE_I386_H
#include "sysdep/ptrace.h"
#include "asm/ptrace-generic.h"
#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
......@@ -29,7 +30,7 @@
#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
#define PT_FIX_EXEC_STACK(sp) do ; while(0)
#define user_mode(r) ((r)->regs.is_user)
#define user_mode(r) UPT_IS_USER(&(r)->regs)
#endif
......
#ifndef _ASM_UM_UCONTEXT_H
#define _ASM_UM_UCONTEXT_H
#include "asm/arch/ucontext.h"
#endif
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