Commit eda5c15d authored by Jeff Dike's avatar Jeff Dike

Resolved the conflict between the skas and get_config changes in

line.h.
parents 341d04a9 38690b28
......@@ -30,6 +30,13 @@ config RWSEM_GENERIC_SPINLOCK
bool
default y
config MODE_TT
bool
default y
config MODE_SKAS
bool
default y
menu "Code maturity level options"
......
#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
ARCH_DIR = arch/um
OS := $(shell uname -s)
......@@ -11,37 +16,31 @@ include/linux/version.h: arch/$(ARCH)/Makefile
# EXTRAVERSION...
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
MAKEBOOT = $(MAKE) -C $(ARCH_DIR)/boot
ifeq ($(CONFIG_DEBUGSYM),y)
DEBUG = -g
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
endif
ifeq ($(CONFIG_GCOV),y)
CFLAGS += -fprofile-arcs -ftest-coverage
endif
ifeq ($(CONFIG_GPROF), y)
PROFILE += -pg -DPROFILING
LINK_PROFILE = $(PROFILE) -Wl,--wrap,__monstartup
endif
CFLAGS-$(CONFIG_DEBUGSYM) += -g
CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage
CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
LINK-$(CONFIG_GPROF) += $(PROFILE) -Wl,--wrap,__monstartup
core-y += $(ARCH_DIR)/kernel/ \
$(ARCH_DIR)/drivers/ \
$(ARCH_DIR)/sys-$(SUBARCH)/
core-$(CONFIG_PT_PROXY) += $(ARCH_DIR)/ptproxy/
ARCH_INCLUDE = $(TOPDIR)/$(ARCH_DIR)/include
ARCH_INCLUDE = -I$(ARCH_DIR)/include
MODE_INCLUDE = -I$(ARCH_DIR)/kernel/tt/include \
-I$(ARCH_DIR)/kernel/skas/include
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
# in CFLAGS. Otherwise, it would cause ld to complain about the two different
# errnos.
CFLAGS += $(DEBUG) $(PROFILE) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-D_LARGEFILE64_SOURCE -I$(ARCH_INCLUDE) -Derrno=kernel_errno
CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
$(MODE_INCLUDE)
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
......@@ -51,10 +50,16 @@ SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
include/asm-um/sigcontext.h include/asm-um/processor.h \
include/asm-um/ptrace.h include/asm-um/arch-signal.h
ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \
$(SYMLINK_HEADERS)
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
ifeq ($(CONFIG_MODE_SKAS), y)
GEN_HEADERS = $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
GEN_HEADERS = $(ARCH_DIR)/include/task.h
$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
endif
GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
......@@ -62,9 +67,9 @@ include $(ARCH_DIR)/Makefile-os-$(OS)
$(ARCH_DIR)/vmlinux.lds.S :
touch $@
prepare: $(ARCH_SYMLINKS) $(GEN_HEADERS)
prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
LDFLAGS_vmlinux = -r $(ARCH_DIR)/main.o
LDFLAGS_vmlinux = -r
vmlinux: $(ARCH_DIR)/main.o
......@@ -74,18 +79,21 @@ $(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
AFLAGS_uml.lds.o = -U$(SUBARCH) -DSTART=$$(($(TOP_ADDR) - $(SIZE))) \
-DELF_ARCH=$(ELF_ARCH) -DELF_FORMAT=\"$(ELF_FORMAT)\" -P -C -Uum
linux: arch/um/uml.lds.s vmlinux
$(CC) -Wl,-T,arch/um/uml.lds.s -o $@ $(LINK_PROFILE) \
$(LINK_WRAPS) -static vmlinux -L/usr/lib -lutil
linux: $(ARCH_DIR)/uml.lds.s vmlinux
$(CC) -Wl,-T,$(ARCH_DIR)/uml.lds.s -static $(LINK-y) $(LINK_WRAPS) \
-o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) -I$(ARCH_INCLUDE)
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
$(MODE_INCLUDE)
# To get a definition of F_SETSIG
USER_CFLAGS += -D_GNU_SOURCE
CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
......@@ -106,7 +114,6 @@ archclean: sysclean
find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
@$(MAKEBOOT) clean
archdep:
for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
......@@ -119,18 +126,28 @@ $(SYMLINK_HEADERS):
include/asm-um/arch:
cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
arch/um/include/sysdep:
cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep
$(ARCH_DIR)/include/sysdep:
cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
arch/um/os:
$(ARCH_DIR)/os:
cd $(ARCH_DIR) && ln -sf os-$(OS) os
$(ARCH_DIR)/include/uml-config.h :
ln -sf $(TOPDIR)/include/linux/autoconf.h $@
$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
$< > $@
$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util FORCE ;
$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
$< > $@
$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
$(ARCH_DIR)/util FORCE ;
$(ARCH_DIR)/util: FORCE
@$(call descend,$@,)
$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
export SUBARCH USER_CFLAGS OS
......@@ -27,7 +27,7 @@ $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
$(SYS_UTIL_DIR)/mk_sc: FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) FORCE ;
$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR): include/asm FORCE
......
......@@ -19,6 +19,8 @@
#include "user.h"
#include "helper.h"
#include "os.h"
#include "choose-mode.h"
#include "mode.h"
void generic_close(int fd, void *unused)
{
......@@ -144,32 +146,6 @@ static int winch_thread(void *arg)
}
}
static int tracer_winch[2];
static void tracer_winch_handler(int sig)
{
char c = 1;
if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
printk("tracer_winch_handler - write failed, errno = %d\n",
errno);
}
/* Called only by the tracing thread during initialization */
void setup_tracer_winch(void)
{
int err;
err = os_pipe(tracer_winch, 1, 1);
if(err){
printk("setup_tracer_winch : os_pipe failed, errno = %d\n",
-err);
return;
}
signal(SIGWINCH, tracer_winch_handler);
}
static int winch_tramp(int fd, void *device_data, int *fd_out)
{
struct winch_data data;
......@@ -212,9 +188,8 @@ void register_winch(int fd, void *device_data)
if(!isatty(fd)) return;
pid = tcgetpgrp(fd);
if(pid == tracing_pid)
register_winch_irq(tracer_winch[0], fd, -1, device_data);
else if(pid == -1){
if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) &&
(pid == -1)){
thread = winch_tramp(fd, device_data, &thread_fd);
if(fd != -1){
register_winch_irq(thread_fd, fd, thread, device_data);
......
......@@ -89,15 +89,26 @@ static int flush_buffer(struct line *line)
return(line->head == line->tail);
}
int line_write(struct line *lines, struct tty_struct *tty, const char *buf,
int len)
int line_write(struct line *lines, struct tty_struct *tty, int from_user,
const char *buf, int len)
{
struct line *line;
char *new;
unsigned long flags;
int n, err, i;
if(tty->stopped) return 0;
if(from_user){
new = kmalloc(len, GFP_KERNEL);
if(new == NULL)
return(0);
n = copy_from_user(new, buf, len);
if(n == len)
return(-EFAULT);
buf = new;
}
i = minor(tty->device) - tty->driver.minor_start;
line = &lines[i];
......@@ -522,7 +533,7 @@ static void winch_cleanup(void)
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
close(winch->fd);
if(winch->pid != -1) os_kill_process(winch->pid);
if(winch->pid != -1) os_kill_process(winch->pid, 0);
}
}
......
......@@ -99,14 +99,13 @@ static int port_accept(struct port_list *port)
}
list_add(&conn->list, &port->pending);
ret = 1;
goto out;
return(1);
out_free:
kfree(conn);
out_close:
os_close_file(fd);
if(pid != -1) os_kill_process(pid);
if(pid != -1) os_kill_process(pid, 0);
out:
return(ret);
}
......@@ -210,9 +209,9 @@ void port_remove_dev(void *d)
struct port_dev *dev = d;
if(dev->helper_pid != -1)
os_kill_process(dev->helper_pid);
os_kill_process(dev->helper_pid, 0);
if(dev->telnetd_pid != -1)
os_kill_process(dev->telnetd_pid);
os_kill_process(dev->telnetd_pid, 0);
dev->helper_pid = -1;
}
......@@ -275,8 +274,8 @@ void port_kern_free(void *d)
{
struct port_dev *dev = d;
if(dev->helper_pid != -1) os_kill_process(dev->telnetd_pid);
if(dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid);
if(dev->helper_pid != -1) os_kill_process(dev->helper_pid, 0);
if(dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid, 0);
kfree(dev);
}
......
......@@ -111,7 +111,7 @@ int pty_open(int input, int output, int primary, void *d, char **dev_out)
if(fd < 0) return(-errno);
info.fd = fd;
tracing_cb(grantpt_cb, &info);
initial_thread_cb(grantpt_cb, &info);
unlockpt(fd);
if(data->raw) raw(fd, 0);
......
......@@ -113,12 +113,12 @@ static void ssl_close(struct tty_struct *tty, struct file * filp)
static int ssl_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
return(line_write(serial_lines, tty, buf, count));
return(line_write(serial_lines, tty, from_user, buf, count));
}
static void ssl_put_char(struct tty_struct *tty, unsigned char ch)
{
line_write(serial_lines, tty, &ch, sizeof(ch));
line_write(serial_lines, tty, 0, &ch, sizeof(ch));
}
static void ssl_flush_chars(struct tty_struct *tty)
......
......@@ -148,7 +148,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
static int con_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count)
{
return(line_write(vts, tty, buf, count));
return(line_write(vts, tty, from_user, buf, count));
}
static void set_termios(struct tty_struct *tty, struct termios * old)
......
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __CHOOSE_MODE_H__
#define __CHOOSE_MODE_H__
#include "uml-config.h"
#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas))
#elif defined(CONFIG_MODE_SKAS)
#define CHOOSE_MODE(tt, skas) (skas)
#elif defined(CONFIG_MODE_TT)
#define CHOOSE_MODE(tt, skas) (tt)
#endif
#define CHOOSE_MODE_PROC(tt, skas, args...) \
CHOOSE_MODE(tt(args), skas(args))
#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:
*/
......@@ -8,34 +8,34 @@
#include "sysdep/frame.h"
struct sc_frame {
struct frame_common {
void *data;
int len;
int sig_index;
int sc_index;
int sr_index;
int sr_relative;
int sp_index;
};
struct sc_frame {
struct frame_common common;
int sc_index;
struct arch_frame_data arch;
};
extern struct sc_frame signal_frame_sc;
extern struct sc_frame signal_frame_sc_sr;
struct si_frame {
void *data;
int len;
int sig_index;
struct frame_common common;
int sip_index;
int si_index;
int sr_index;
int sr_relative;
int sp_index;
};
extern struct si_frame signal_frame_si;
extern void capture_signal_stack(void);
extern void set_sc_ip_sp(void *sc_ptr, unsigned long ip, unsigned long sp);
#endif
......
......@@ -15,23 +15,27 @@ extern char *gdb_init;
extern int kmalloc_ok;
extern int timer_irq_inited;
extern int jail;
extern int nsyscalls;
extern struct task_struct *idle_threads[NR_CPUS];
#define ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define ROUND_UP(addr) ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define UML_ROUND_UP(addr) \
UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
extern unsigned long stack_sp(unsigned long page);
extern int kernel_thread_proc(void *data);
extern void syscall_segv(int sig);
extern int current_pid(void);
extern void set_init_pid(int pid);
extern unsigned long alloc_stack(int order, int atomic);
extern int do_signal(int error);
extern int is_stack_fault(unsigned long sp);
extern unsigned long segv(unsigned long address, unsigned long ip,
int is_write, int is_user, void *sc_ptr);
extern int set_user_mode(void *task);
int is_write, int is_user, void *sc);
extern unsigned long handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user,
int *code_out);
extern void syscall_ready(void);
extern void set_tracing(void *t, int tracing);
extern int is_tracing(void *task);
......@@ -40,7 +44,6 @@ extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
extern int page_size(void);
extern int page_mask(void);
extern int need_finish_fork(void);
extern int do_proc_op(void *t, int proc_id);
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);
......@@ -57,7 +60,6 @@ extern int next_trap_index(int max);
extern void default_idle(void);
extern void finish_fork(void);
extern void paging_init(void);
extern unsigned long um_virt_to_phys(void *t, unsigned long addr);
extern void init_flush_vm(void);
extern void *syscall_sp(void *t);
extern void syscall_trace(void);
......@@ -68,9 +70,7 @@ extern int external_pid(void *t);
extern int pid_to_processor_id(int pid);
extern void boot_timer_handler(int sig);
extern void interrupt_end(void);
extern void tracing_reboot(void);
extern void tracing_halt(void);
extern void tracing_cb(void (*proc)(void *), void *arg);
extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int debugger_signal(int status, int pid);
extern void debugger_parent_signal(int status, int pid);
extern void child_signal(int pid, int status);
......@@ -78,25 +78,19 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
extern int init_parent_proxy(int pid);
extern void check_stack_overflow(void *ptr);
extern void relay_signal(int sig, struct uml_pt_regs *regs);
extern int singlestepping(void *t);
extern void clear_singlestep(void *t);
extern void not_implemented(void);
extern int user_context(unsigned long sp);
extern void timer_irq(struct 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);
extern void *round_up(unsigned long addr);
extern void *round_down(unsigned long addr);
extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
extern int config_gdb(char *str);
extern int remove_gdb(void);
extern char *uml_strdup(char *string);
extern void unprotect_kernel_mem(void);
extern void protect_kernel_mem(void);
extern unsigned long get_kmem_end(void);
extern void set_kmem_end(unsigned long);
extern void set_task_sizes(int arg);
extern void uml_cleanup(void);
extern int pid_to_processor_id(int pid);
extern void set_current(void *t);
......@@ -107,7 +101,6 @@ 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 set_thread_sc(void *sc);
extern void bus_handler(int sig, struct uml_pt_regs *regs);
extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
......@@ -116,7 +109,6 @@ extern struct task_struct *get_task(int pid, int require);
extern void machine_halt(void);
extern int is_syscall(unsigned long addr);
extern void arch_switch(void);
extern int is_valid_pid(int pid);
extern void free_irq(unsigned int, void *);
extern int um_in_interrupt(void);
extern int cpu(void);
......
......@@ -74,7 +74,7 @@ extern int line_open(struct line *lines, struct tty_struct *tty,
struct chan_opts *opts);
extern int line_setup(struct line *lines, int num, char *init,
int all_allowed);
extern int line_write(struct line *line, struct tty_struct *tty,
extern int line_write(struct line *line, struct tty_struct *tty, int from_user,
const char *buf, int len);
extern int line_write_room(struct tty_struct *tty);
extern char *add_xterm_umid(char *base);
......
......@@ -54,11 +54,6 @@ extern int create_mem_file(unsigned long len);
extern void setup_range(int fd, char *driver, unsigned long start,
unsigned long pfn, unsigned long total, int need_vm,
struct mem_region *region, void *reserved);
extern void map(unsigned long virt, unsigned long p, unsigned long len,
int r, int w, int x);
extern int unmap(void *addr, int len);
extern int protect(unsigned long addr, unsigned long len, int r, int w,
int x, int must_succeed);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
extern int init_maps(struct mem_region *region);
......@@ -68,10 +63,15 @@ extern unsigned long get_vm(unsigned long len);
extern void setup_physmem(unsigned long start, unsigned long usable,
unsigned long len);
extern int setup_region(struct mem_region *region, void *entry);
extern void add_iomem(char *name, int fd, int size);
extern void add_iomem(char *name, int fd, unsigned long size);
extern struct mem_region *phys_region(unsigned long phys);
extern unsigned long phys_offset(unsigned long phys);
extern void unmap_physmem(void);
extern int map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
extern int protect_memory(unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern unsigned long get_kmem_end(void);
#endif
......
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __MODE_H__
#define __MODE_H__
#include "uml-config.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/mode.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/mode.h"
#endif
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __MODE_KERN_H__
#define __MODE_KERN_H__
#include "linux/config.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/mode_kern.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/mode_kern.h"
#endif
#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:
*/
......@@ -103,10 +103,16 @@ extern int os_write_file(int fd, char *buf, int count);
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_stop_process(int pid);
extern void os_kill_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_usr1_process(int pid);
extern int os_getpid(void);
extern int os_map_memory(void *virt, int fd, unsigned long off,
unsigned long len, int r, int w, int x);
extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
#endif
/*
......
/*
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SYSCALL_USER_H__
#define __SYSCALL_USER_H__
#ifndef __SYSCALL_USER_H
#define __SYSCALL_USER_H
#include <asm/sigcontext.h>
extern void syscall_handler(int sig, struct uml_pt_regs *regs);
extern void exit_kernel(int pid, void *task);
extern int do_syscall(void *task, int pid);
extern int record_syscall_start(int syscall);
extern void record_syscall_end(int index, int result);
#endif
......
......@@ -20,7 +20,8 @@ static inline void *sp_to_rt_sc(unsigned long sp)
{
unsigned long sc;
sc = sp - signal_frame_si.sp_index + signal_frame_si.len - 4;
sc = sp - signal_frame_si.common.sp_index +
signal_frame_si.common.len - 4;
return((void *) sc);
}
......@@ -28,7 +29,8 @@ static inline void *sp_to_mask(unsigned long sp)
{
unsigned long mask;
mask = sp - signal_frame_sc.sp_index + signal_frame_sc.len - 8;
mask = sp - signal_frame_sc.common.sp_index +
signal_frame_sc.common.len - 8;
return((void *) mask);
}
......@@ -38,7 +40,8 @@ static inline void *sp_to_rt_mask(unsigned long sp)
{
unsigned long mask;
mask = sp - signal_frame_si.sp_index + signal_frame_si.len +
mask = sp - signal_frame_si.common.sp_index +
signal_frame_si.common.len +
sc_size(&signal_frame_sc.arch) - 4;
return((void *) mask);
}
......
/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
#include "sysdep/sc.h"
#include "uml-config.h"
#include "ptrace-tt.h"
#include "ptrace-skas.h"
#include "choose-mode.h"
struct uml_pt_regs {
unsigned long args[6];
long syscall;
int is_user;
void *sc;
union {
#ifdef CONFIG_MODE_TT
void *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;
#endif
} mode;
};
#define EMPTY_UML_PT_REGS { \
syscall : -1, \
args : { [0 ... 5] = 0 }, \
is_user : 0, \
sc : NULL }
#define UPT_IP(regs) SC_IP((regs)->sc)
#define UPT_SP(regs) SC_SP((regs)->sc)
#define UPT_EFLAGS(regs) SC_EFLAGS((regs)->sc)
#define UPT_EAX(regs) SC_EAX((regs)->sc)
#define UPT_EBX(regs) SC_EBX((regs)->sc)
#define UPT_ECX(regs) SC_ECX((regs)->sc)
#define UPT_EDX(regs) SC_EDX((regs)->sc)
#define UPT_ESI(regs) SC_ESI((regs)->sc)
#define UPT_EDI(regs) SC_EDI((regs)->sc)
#define UPT_EBP(regs) SC_EBP((regs)->sc)
#define UPT_ORIG_EAX(regs) ((regs)->syscall)
#define UPT_CS(regs) SC_CS((regs)->sc)
#define UPT_SS(regs) SC_SS((regs)->sc)
#define UPT_DS(regs) SC_DS((regs)->sc)
#define UPT_ES(regs) SC_ES((regs)->sc)
#define UPT_FS(regs) SC_FS((regs)->sc)
#define UPT_GS(regs) SC_GS((regs)->sc)
#define UPT_SC(regs) ((regs)->sc)
is_user : 0 }
extern int mode_tt;
#define UPT_IP(r) \
CHOOSE_MODE(SC_IP((r)->mode.tt), REGS_IP((r)->mode.skas.regs))
#define UPT_SP(r) \
CHOOSE_MODE(SC_SP((r)->mode.tt), REGS_SP((r)->mode.skas.regs))
#define UPT_EFLAGS(r) \
CHOOSE_MODE(SC_EFLAGS((r)->mode.tt), REGS_EFLAGS((r)->mode.skas.regs))
#define UPT_EAX(r) \
CHOOSE_MODE(SC_EAX((r)->mode.tt), REGS_EAX((r)->mode.skas.regs))
#define UPT_EBX(r) \
CHOOSE_MODE(SC_EBX((r)->mode.tt), REGS_EBX((r)->mode.skas.regs))
#define UPT_ECX(r) \
CHOOSE_MODE(SC_ECX((r)->mode.tt), REGS_ECX((r)->mode.skas.regs))
#define UPT_EDX(r) \
CHOOSE_MODE(SC_EDX((r)->mode.tt), REGS_EDX((r)->mode.skas.regs))
#define UPT_ESI(r) \
CHOOSE_MODE(SC_ESI((r)->mode.tt), REGS_ESI((r)->mode.skas.regs))
#define UPT_EDI(r) \
CHOOSE_MODE(SC_EDI((r)->mode.tt), REGS_EDI((r)->mode.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)
#define UPT_CS(r) \
CHOOSE_MODE(SC_CS((r)->mode.tt), REGS_CS((r)->mode.skas.regs))
#define UPT_SS(r) \
CHOOSE_MODE(SC_SS((r)->mode.tt), REGS_SS((r)->mode.skas.regs))
#define UPT_DS(r) \
CHOOSE_MODE(SC_DS((r)->mode.tt), REGS_DS((r)->mode.skas.regs))
#define UPT_ES(r) \
CHOOSE_MODE(SC_ES((r)->mode.tt), REGS_ES((r)->mode.skas.regs))
#define UPT_FS(r) \
CHOOSE_MODE(SC_FS((r)->mode.tt), REGS_FS((r)->mode.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)
#define UPT_REG(regs, reg) \
({ unsigned long val; \
......@@ -94,12 +128,29 @@ struct uml_pt_regs {
} \
} while (0)
#define UPT_SET_SYSCALL_RETURN(regs, res) \
SC_SET_SYSCALL_RETURN((regs)->sc, (res))
#define UPT_RESTART_SYSCALL(regs) SC_RESTART_SYSCALL((regs)->sc)
#define UPT_ORIG_SYSCALL(regs) UPT_EAX(regs)
#define UPT_SYSCALL_NR(regs) ((regs)->syscall)
#define UPT_SYSCALL_RET(regs) UPT_EAX(regs)
#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)))
#define UPT_RESTART_SYSCALL(r) \
CHOOSE_MODE(SC_RESTART_SYSCALL((r)->mode.tt), \
REGS_RESTART_SYSCALL((r)->mode.skas.regs))
#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
#define UPT_SYSCALL_NR(r) ((r)->syscall)
#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))
#define UPT_FAULT_ADDR(r) \
CHOOSE_MODE(SC_FAULT_ADDR(r->mode.tt), \
REGS_FAULT_ADDR(&r->mode.skas))
#define UPT_FAULT_WRITE(r) \
CHOOSE_MODE(SC_FAULT_WRITE(r->mode.tt), \
REGS_FAULT_WRITE(&r->mode.skas))
#endif
......
......@@ -6,13 +6,22 @@
#ifndef __SYS_SIGCONTEXT_I386_H
#define __SYS_SIGCONTEXT_I386_H
#include "sc.h"
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
#define SC_SET_SYSCALL_RETURN(sc, result) do SC_EAX(sc) = (result) ; while(0)
#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
#define SC_FAULT_ADDR(sc) SC_CR2(sc)
#define SC_FAULT_WRITE(sc) (SC_ERR(sc) & 2)
#define SC_FAULT_TYPE(sc) SC_ERR(sc)
#define FAULT_WRITE(err) (err & 2)
#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0)
#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
/* ptrace expects that, at the start of a system call, %eax contains
* -ENOSYS, so this makes it so.
......@@ -20,10 +29,12 @@
#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
/* These are General Protection and Page Fault */
#define SEGV_IS_FIXABLE(sc) ((SC_TRAPNO(sc) == 13) || (SC_TRAPNO(sc) == 14))
#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
/* XXX struct sigcontext needs declaring by now */
#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)
{
......@@ -35,6 +46,20 @@ static inline void sc_to_regs(struct uml_pt_regs *regs, struct sigcontext *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);
......
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __ARCH_UM_MMU_H
#define __ARCH_UM_MMU_H
#include "linux/config.h"
#include "choose-mode.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/mmu.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/mmu.h"
#endif
typedef union {
#ifdef CONFIG_MODE_TT
struct mmu_context_tt tt;
#endif
#ifdef CONFIG_MODE_SKAS
struct mmu_context_skas skas;
#endif
} mm_context_t;
#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:
*/
......@@ -8,6 +8,8 @@
#include "sysdep/ptrace.h"
extern int mode_tt;
extern int grantpt(int __fd);
extern int unlockpt(int __fd);
extern char *ptsname(int __fd);
......@@ -21,6 +23,13 @@ struct cpu_task {
extern struct cpu_task cpu_tasks[];
struct signal_info {
void (*handler)(int, struct uml_pt_regs *);
int is_irq;
};
extern struct signal_info sig_info[];
extern unsigned long low_physmem;
extern unsigned long high_physmem;
extern unsigned long uml_physmem;
......@@ -29,16 +38,11 @@ extern unsigned long end_vm;
extern unsigned long start_vm;
extern unsigned long highmem;
extern int tracing_pid;
extern int honeypot;
extern char host_info[];
extern char saved_command_line[];
extern char command_line[];
extern int gdb_pid;
extern char *tempdir;
extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
......@@ -51,12 +55,10 @@ extern int pty_close_sigio;
extern void stop(void);
extern void stack_protections(unsigned long address);
extern void task_protections(unsigned long address);
extern int signals(int (*init_proc)(void *), void *sp);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern void *add_signal_handler(int sig, void (*handler)(int));
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
extern void trace_myself(void);
extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
extern int linux_main(int argc, char **argv);
extern void remap_data(void *segment_start, void *segment_end, int w);
......@@ -69,13 +71,13 @@ extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(void);
extern void add_arg(char *cmd_line, char *arg);
extern void init_new_thread(void *sig_stack, void (*usr1_handler)(int));
extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
extern void init_new_thread_signals(int altstack);
extern void attach_process(int pid);
extern int fork_tramp(void *sig_stack);
extern void do_exec(int old_pid, int new_pid);
extern void tracer_panic(char *msg, ...);
extern char *get_umid(int only_if_set);
extern void do_longjmp(void *p);
extern void do_longjmp(void *p, int val);
extern void suspend_new_thread(int fd);
extern int detach(int pid, int sig);
extern int attach(int pid);
......@@ -89,6 +91,7 @@ extern void arch_check_bugs(void);
extern int arch_handle_signal(int sig, struct 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);
#endif
......
#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
EXTRA_TARGETS := unmap_fin.o
obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \
helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
obj-y = config.o exec_kern.o exitcode.o frame_kern.o frame.o helper.o \
init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.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 uaccess_user.o um_arch.o \
umid.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
# user_syms.o not included here because Rules.make has its own ideas about
# building anything in export-objs
USER_OBJS := $(filter %_user.o,$(obj-y)) config.o helper.o process.o \
tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/kernel/$(file))
export-objs := ksyms.o process_kern.o signal_kern.o gprof_syms.o gmon_syms.o
USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
ifeq ($(CONFIG_MODULES), y)
DMODULES = -D__CONFIG_MODULES__
endif
DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
ifeq ($(CONFIG_MODVERSIONS), y)
DMODVERSIONS = -D__CONFIG_MODVERSIONS__
endif
export-objs-$(CONFIG_GPROF) += gprof_syms.o
export-objs-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
export-objs := ksyms.o process_kern.o signal_kern.o $(export-objs-y)
CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES) $(DMODVERSIONS) \
CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-I/usr/include -I../include
CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
......@@ -44,27 +51,28 @@ include $(TOPDIR)/Rules.make
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
arch/um/kernel/unmap.o: arch/um/kernel/unmap.c
$(obj)/unmap.o: $(src)/unmap.c
$(CC) $(UNMAP_CFLAGS) -c -o $@ $<
arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o
$(obj)/unmap_fin.o : $(src)/unmap.o
ld -r -o $@ $< -lc -L/usr/lib
# This has to be separate because it needs be compiled with frame pointers
# regardless of how the rest of the kernel is built.
arch/um/kernel/frame.o: arch/um/kernel/frame.c
$(obj)/frame.o: $(src)/frame.c
$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
arch/um/kernel/config.c : arch/um/kernel/config.c.in $(TOPDIR)/.config
$(PERL) -e $(QUOTE) < arch/um/kernel/config.c.in > $@
$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
arch/um/kernel/config.o : arch/um/kernel/config.c
$(obj)/config.o : $(obj)/config.c
clean:
rm -f config.c
for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
modules:
......
......@@ -18,65 +18,17 @@
#include "2_5compat.h"
#include "os.h"
#include "time_user.h"
/* See comment above fork_tramp for why sigstop is defined and used like
* this
*/
static int sigstop = SIGSTOP;
static int exec_tramp(void *sig_stack)
{
int sig = sigstop;
init_new_thread(sig_stack, NULL);
kill(os_getpid(), sig);
return(0);
}
#include "choose-mode.h"
#include "mode_kern.h"
void flush_thread(void)
{
unsigned long stack;
int new_pid;
stack = alloc_stack(0, 0);
if(stack == 0){
printk(KERN_ERR
"flush_thread : failed to allocate temporary stack\n");
do_exit(SIGKILL);
}
new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
stack, 0, exec_tramp);
if(new_pid < 0){
printk(KERN_ERR
"flush_thread : new thread failed, errno = %d\n",
-new_pid);
do_exit(SIGKILL);
}
if(current->thread_info->cpu == 0)
forward_interrupts(new_pid);
current->thread.request.op = OP_EXEC;
current->thread.request.u.exec.pid = new_pid;
unprotect_stack((unsigned long) current->thread_info);
os_usr1_process(os_getpid());
enable_timer();
free_page(stack);
protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
task_protections((unsigned long) current->thread_info);
force_flush_all();
unblock_signals();
CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
}
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
set_fs(USER_DS);
flush_tlb_mm(current->mm);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
PT_FIX_EXEC_STACK(esp);
CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
static int execve1(char *file, char **argv, char **env)
......@@ -93,8 +45,12 @@ static int execve1(char *file, char **argv, char **env)
int um_execve(char *file, char **argv, char **env)
{
if(execve1(file, argv, env) == 0) do_longjmp(current->thread.jmp);
return(-1);
int err;
err = execve1(file, argv, env);
if(!err)
do_longjmp(current->thread.exec_buf, 1);
return(err);
}
int sys_execve(char *file, char **argv, char **env)
......
......@@ -12,6 +12,7 @@
#include <sched.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <asm/page.h>
#include <asm/ptrace.h>
......@@ -84,8 +85,8 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
printf("capture_stack : waitpid failed - errno = %d\n", errno);
exit(1);
}
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
printf("capture_stack : Expected exit status 0, "
if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){
printf("capture_stack : Expected exit signal 9, "
"got status = 0x%x\n", status);
exit(1);
}
......@@ -103,28 +104,61 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
return(len);
}
static void child_common(void *sp, int size, sighandler_t handler, int flags)
struct common_raw {
void *stack;
int size;
unsigned long sig;
unsigned long sr;
unsigned long sp;
};
#define SA_RESTORER (0x04000000)
typedef unsigned long old_sigset_t;
struct old_sigaction {
__sighandler_t handler;
old_sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
static void child_common(struct common_raw *common, sighandler_t handler,
int restorer, int flags)
{
stack_t ss;
struct sigaction sa;
stack_t ss = ((stack_t) { .ss_sp = common->stack,
.ss_flags = 0,
.ss_size = common->size });
int err;
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
printf("PTRACE_TRACEME failed, errno = %d\n", errno);
}
ss.ss_sp = sp;
ss.ss_flags = 0;
ss.ss_size = size;
if(sigaltstack(&ss, NULL) < 0){
printf("sigaltstack failed - errno = %d\n", errno);
_exit(1);
kill(getpid(), SIGKILL);
}
if(restorer){
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONSTACK | flags;
if(sigaction(SIGUSR1, &sa, NULL) < 0){
err = sigaction(SIGUSR1, &sa, NULL);
}
else {
struct old_sigaction sa;
sa.handler = handler;
sa.sa_mask = 0;
sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER;
err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL);
}
if(err < 0){
printf("sigaction failed - errno = %d\n", errno);
_exit(1);
kill(getpid(), SIGKILL);
}
os_stop_process(os_getpid());
......@@ -133,13 +167,12 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags)
/* Changed only during early boot */
struct sc_frame signal_frame_sc;
struct sc_frame signal_frame_sc_sr;
struct sc_frame_raw {
void *stack;
int size;
unsigned long sig;
struct common_raw common;
unsigned long sc;
unsigned long sr;
unsigned long sp;
int restorer;
struct arch_frame_data_raw arch;
};
......@@ -148,20 +181,20 @@ static struct sc_frame_raw *raw_sc = NULL;
static void sc_handler(int sig, struct sigcontext sc)
{
raw_sc->sig = (unsigned long) &sig;
raw_sc->common.sig = (unsigned long) &sig;
raw_sc->common.sr = frame_restorer();
raw_sc->common.sp = frame_sp();
raw_sc->sc = (unsigned long) &sc;
raw_sc->sr = frame_restorer();
raw_sc->sp = frame_sp();
setup_arch_frame_raw(&raw_sc->arch, &sc);
os_stop_process(os_getpid());
_exit(0);
kill(getpid(), SIGKILL);
}
static int sc_child(void *arg)
{
raw_sc = arg;
child_common(raw_sc->stack, raw_sc->size, (sighandler_t) sc_handler,
0);
child_common(&raw_sc->common, (sighandler_t) sc_handler,
raw_sc->restorer, 0);
return(-1);
}
......@@ -169,13 +202,9 @@ static int sc_child(void *arg)
struct si_frame signal_frame_si;
struct si_frame_raw {
void *stack;
int size;
unsigned long sig;
struct common_raw common;
unsigned long sip;
unsigned long si;
unsigned long sr;
unsigned long sp;
};
/* Changed only during early boot */
......@@ -183,23 +212,59 @@ static struct si_frame_raw *raw_si = NULL;
static void si_handler(int sig, siginfo_t *si)
{
raw_si->sig = (unsigned long) &sig;
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->sr = frame_restorer();
raw_si->sp = frame_sp();
os_stop_process(os_getpid());
_exit(0);
kill(getpid(), SIGKILL);
}
static int si_child(void *arg)
{
raw_si = arg;
child_common(raw_si->stack, raw_si->size, (sighandler_t) si_handler,
child_common(&raw_si->common, (sighandler_t) si_handler, 1,
SA_SIGINFO);
return(-1);
}
static int relative_sr(unsigned long sr, int sr_index, void *stack,
void *framep)
{
unsigned long *srp = (unsigned long *) sr;
unsigned long frame = (unsigned long) framep;
if((*srp & PAGE_MASK) == (unsigned long) stack){
*srp -= sr;
*((unsigned long *) (frame + sr_index)) = *srp;
return(1);
}
else return(0);
}
static unsigned long capture_stack_common(int (*proc)(void *), void *arg,
struct common_raw *common_in,
void *top, void *sigstack,
int stack_len,
struct frame_common *common_out)
{
unsigned long sig_top = (unsigned long) sigstack + stack_len, base;
common_in->stack = (void *) sigstack;
common_in->size = stack_len;
common_out->len = capture_stack(proc, arg, top, sig_top,
&common_out->data);
base = sig_top - common_out->len;
common_out->sig_index = common_in->sig - base;
common_out->sp_index = common_in->sp - base;
common_out->sr_index = common_in->sr - base;
common_out->sr_relative = relative_sr(common_in->sr,
common_out->sr_index, sigstack,
common_out->data);
return(base);
}
void capture_signal_stack(void)
{
struct sc_frame_raw raw_sc;
......@@ -220,54 +285,29 @@ void capture_signal_stack(void)
top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
sig_top = (unsigned long) sigstack + PAGE_SIZE;
raw_sc.stack = sigstack;
raw_sc.size = PAGE_SIZE;
signal_frame_sc.len = capture_stack(sc_child, &raw_sc, (void *) top,
sig_top, &signal_frame_sc.data);
/* These are the offsets within signal_frame_sc.data (counting from
* the bottom) of sig, sc, SA_RESTORER, and the initial sp.
*/
/* Get the sigcontext, no sigrestorer layout */
raw_sc.restorer = 0;
base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
(void *) top, sigstack, PAGE_SIZE,
&signal_frame_sc.common);
base = sig_top - signal_frame_sc.len;
signal_frame_sc.sig_index = raw_sc.sig - base;
signal_frame_sc.sc_index = raw_sc.sc - base;
signal_frame_sc.sr_index = raw_sc.sr - base;
if((*((unsigned long *) raw_sc.sr) & PAGE_MASK) ==
(unsigned long) sigstack){
unsigned long *sr = (unsigned long *) raw_sc.sr;
unsigned long frame = (unsigned long) signal_frame_sc.data;
signal_frame_sc.sr_relative = 1;
*sr -= raw_sc.sr;
*((unsigned long *) (frame + signal_frame_sc.sr_index)) = *sr;
}
else signal_frame_sc.sr_relative = 0;
signal_frame_sc.sp_index = raw_sc.sp - base;
setup_arch_frame(&raw_sc.arch, &signal_frame_sc.arch);
/* Repeat for the siginfo variant */
/* Ditto for the sigcontext, sigrestorer layout */
raw_sc.restorer = 1;
base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
(void *) top, sigstack, PAGE_SIZE,
&signal_frame_sc_sr.common);
signal_frame_sc_sr.sc_index = raw_sc.sc - base;
/* And the siginfo layout */
raw_si.stack = sigstack;
raw_si.size = PAGE_SIZE;
signal_frame_si.len = capture_stack(si_child, &raw_si, (void *) top,
sig_top, &signal_frame_si.data);
base = sig_top - signal_frame_si.len;
signal_frame_si.sig_index = raw_si.sig - base;
base = capture_stack_common(si_child, &raw_si, &raw_si.common,
(void *) top, sigstack, PAGE_SIZE,
&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.sr_index = raw_si.sr - base;
if((*((unsigned long *) raw_si.sr) & PAGE_MASK) ==
(unsigned long) sigstack){
unsigned long *sr = (unsigned long *) raw_si.sr;
unsigned long frame = (unsigned long) signal_frame_si.data;
signal_frame_sc.sr_relative = 1;
*sr -= raw_si.sr;
*((unsigned long *) (frame + signal_frame_si.sr_index)) = *sr;
}
else signal_frame_si.sr_relative = 0;
signal_frame_si.sp_index = raw_si.sp - base;
if((munmap(stack, PAGE_SIZE) < 0) ||
(munmap(sigstack, PAGE_SIZE) < 0)){
......@@ -277,14 +317,6 @@ void capture_signal_stack(void)
}
}
void set_sc_ip_sp(void *sc_ptr, unsigned long ip, unsigned long sp)
{
struct sigcontext *sc = sc_ptr;
SC_IP(sc) = ip;
SC_SP(sc) = sp;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -13,16 +13,16 @@
static int copy_restorer(void (*restorer)(void), unsigned long start,
unsigned long sr_index, int sr_relative)
{
if(restorer != 0){
if(copy_to_user((void *) (start + sr_index), &restorer,
sizeof(restorer)))
return(1);
}
else if(sr_relative){
unsigned long *sr = (unsigned long *) (start + sr_index);
*sr += (unsigned long) sr;
unsigned long sr;
if(sr_relative){
sr = (unsigned long) restorer;
sr += start + sr_index;
restorer = (void (*)(void)) sr;
}
return(0);
return(copy_to_user((void *) (start + sr_index), &restorer,
sizeof(restorer)));
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
......@@ -34,27 +34,31 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
void *sip;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
start = stack_top - signal_frame_si.len -
start = stack_top - signal_frame_si.common.len -
sc_size(&signal_frame_sc.arch) - sig_size;
sip = (void *) (start + signal_frame_si.si_index);
sc = start + signal_frame_si.len;
sc = start + signal_frame_si.common.len;
sigs = sc + sc_size(&signal_frame_sc.arch);
if(copy_sc_to_user((void *) sc, regs->regs.sc,
if(restorer == NULL)
panic("setup_signal_stack_si - no restorer");
if(copy_sc_to_user((void *) sc, regs->regs.mode.tt,
&signal_frame_sc.arch) ||
copy_to_user((void *) start, signal_frame_si.data,
signal_frame_si.len) ||
copy_to_user((void *) (start + signal_frame_si.sig_index), &sig,
sizeof(sig)) ||
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_restorer(restorer, start, signal_frame_si.sr_index,
signal_frame_si.sr_relative))
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.sp_index;
PT_REGS_SP(regs) = start + signal_frame_sc.common.sp_index;
return(0);
}
......@@ -62,26 +66,36 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void),
struct pt_regs *regs, sigset_t *mask)
{
struct frame_common *frame = &signal_frame_sc_sr.common;
void *user_sc;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
unsigned long sigs, start = stack_top - signal_frame_sc.len - sig_size;
void *user_sc = (void *) (start + signal_frame_sc.sc_index);
unsigned long sigs, sr;
unsigned long start = stack_top - frame->len - sig_size;
sigs = start + signal_frame_sc.len;
if(copy_to_user((void *) start, signal_frame_sc.data,
signal_frame_sc.len) ||
copy_to_user((void *) (start + signal_frame_sc.sig_index), &sig,
user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
if(restorer == NULL){
frame = &signal_frame_sc.common;
user_sc = (void *) (start + signal_frame_sc.sc_index);
sr = (unsigned long) frame->data;
sr += frame->sr_index;
sr = *((unsigned long *) sr);
restorer = ((void (*)(void)) sr);
}
sigs = start + frame->len;
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->regs.sc, &signal_frame_sc.arch) ||
copy_sc_to_user(user_sc, regs->regs.mode.tt,
&signal_frame_sc.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, signal_frame_sc.sr_index,
signal_frame_sc.sr_relative))
copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
PT_REGS_SP(regs) = start + signal_frame_sc.sp_index;
PT_REGS_SP(regs) = start + frame->sp_index;
set_sc_ip_sp(regs->regs.sc, handler, start + signal_frame_sc.sp_index);
return(0);
}
......
......@@ -43,9 +43,12 @@ static int helper_child(void *arg)
execvp(argv[0], argv);
printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
write(data->fd, &errno, sizeof(errno));
_exit(1);
os_kill_process(os_getpid(), 0);
return(0);
}
/* XXX The alloc_stack here breaks if this is called in the tracing thread */
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
unsigned long *stack_out)
{
......
......@@ -47,7 +47,7 @@ struct task_struct *alloc_task_struct(void){
void unprotect_stack(unsigned long stack)
{
protect(stack, 4 * PAGE_SIZE, 1, 1, 0, 1);
protect_memory(stack, 4 * PAGE_SIZE, 1, 1, 0, 1);
}
void free_task_struct(struct task_struct *task)
......
/*
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/config.h"
#include "linux/module.h"
#include "linux/string.h"
......@@ -19,17 +24,13 @@
EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__const_udelay);
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(sys_waitpid);
EXPORT_SYMBOL(task_size);
EXPORT_SYMBOL(__do_copy_from_user);
EXPORT_SYMBOL(__do_copy_to_user);
EXPORT_SYMBOL(__do_strncpy_from_user);
EXPORT_SYMBOL(__do_strnlen_user);
EXPORT_SYMBOL(flush_tlb_range);
EXPORT_SYMBOL(__do_clear_user);
EXPORT_SYMBOL(honeypot);
EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
......@@ -37,10 +38,10 @@ EXPORT_SYMBOL(region_pa);
EXPORT_SYMBOL(region_va);
EXPORT_SYMBOL(phys_mem_map);
EXPORT_SYMBOL(page_mem_map);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(page_to_phys);
EXPORT_SYMBOL(phys_to_page);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(os_open_file);
EXPORT_SYMBOL(os_read_file);
......@@ -53,7 +54,6 @@ EXPORT_SYMBOL(helper_wait);
EXPORT_SYMBOL(os_shutdown_socket);
EXPORT_SYMBOL(os_connect_socket);
EXPORT_SYMBOL(run_helper);
EXPORT_SYMBOL(tracing_pid);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(dump_thread);
......@@ -75,6 +75,7 @@ EXPORT_SYMBOL_NOVERS(__write_lock_failed);
extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL_NOVERS(__read_lock_failed);
EXPORT_SYMBOL(smp_num_cpus);
#endif
#ifdef CONFIG_HIGHMEM
......
......@@ -25,6 +25,8 @@
#include "mem.h"
#include "kern.h"
#include "init.h"
#include "os.h"
#include "mode_kern.h"
/* Changed during early boot */
pgd_t swapper_pg_dir[1024];
......@@ -56,12 +58,12 @@ static unsigned long brk_end;
static void map_cb(void *unused)
{
map(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
}
void unmap_physmem(void)
{
unmap((void *) brk_end, uml_reserved - brk_end);
os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
}
extern char __binary_start;
......@@ -81,16 +83,16 @@ void mem_init(void)
/* Map in the area just after the brk now that kmalloc is about
* to be turned on.
*/
brk_end = (unsigned long) ROUND_UP(sbrk(0));
brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
map_cb(NULL);
tracing_cb(map_cb, NULL);
initial_thread_cb(map_cb, NULL);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
/* Fill in any hole at the start of the binary */
start = (unsigned long) &__binary_start;
if(uml_physmem != start){
map(uml_physmem, __pa(uml_physmem), start - uml_physmem,
map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem,
1, 1, 0);
}
......@@ -106,6 +108,21 @@ void mem_init(void)
kmalloc_ok = 1;
}
/* Changed during early boot */
static unsigned long kmem_top = 0;
unsigned long get_kmem_end(void)
{
if(kmem_top == 0)
kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
return(kmem_top);
}
void set_kmem_end(unsigned long new)
{
kmem_top = new;
}
#if CONFIG_HIGHMEM
/* Changed during early boot */
pte_t *kmap_pte;
......@@ -379,20 +396,6 @@ void show_mem(void)
printk("%d pages swap cached\n", cached);
}
/* Changed during early boot */
static unsigned long kmem_top = 0;
unsigned long get_kmem_end(void)
{
if(kmem_top == 0) kmem_top = host_task_size - ABOVE_KMEM;
return(kmem_top);
}
void set_kmem_end(unsigned long new)
{
kmem_top = new;
}
static int __init uml_mem_setup(char *line, int *add)
{
char *retptr;
......@@ -513,7 +516,7 @@ unsigned long get_vm(unsigned long len)
return(0);
found:
up(&vm_reserved_sem);
start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE;
start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
err = reserve_vm(start, start + len, NULL);
if(err) return(0);
return(start);
......@@ -562,7 +565,7 @@ struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
int num_iomem_regions = 0;
void add_iomem(char *name, int fd, int size)
void add_iomem(char *name, int fd, unsigned long size)
{
if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
return;
......
......@@ -181,41 +181,19 @@ void log(char *fmt, ...)
}
#endif
void map(unsigned long virt, unsigned long phys, unsigned long len,
int map_memory(unsigned long virt, unsigned long phys, unsigned long len,
int r, int w, int x)
{
struct mem_region *region;
void *loc;
int prot;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
region = phys_region(phys);
loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
region->fd, phys_offset(phys));
if(loc != (void *) virt){
panic("Error mapping a page - errno = %d", errno);
}
}
int unmap(void *addr, int len)
{
int err;
struct mem_region *region = phys_region(phys);
err = munmap(addr, len);
if(err < 0) return(-errno);
else return(err);
return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
r, w, x));
}
int protect(unsigned long addr, unsigned long len, int r, int w, int x,
int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
int must_succeed)
{
int prot;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
if(mprotect((void *) addr, len, prot) == -1){
if(os_protect_memory((void *) addr, len, r, w, x) < 0){
if(must_succeed)
panic("protect failed, errno = %d", errno);
else return(-errno);
......
......@@ -21,9 +21,6 @@
#include <asm/sigcontext.h>
#include <asm/unistd.h>
#include <asm/page.h>
#ifdef PROFILING
#include <sys/gmon.h>
#endif
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
......@@ -33,13 +30,18 @@
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
#include "irq_user.h"
#include "syscall_user.h"
#include "ptrace_user.h"
#include "time_user.h"
#include "init.h"
#include "os.h"
#include "uml-config.h"
#include "choose-mode.h"
#include "mode.h"
#ifdef CONFIG_MODE_SKAS
#include "skas_ptrace.h"
#endif
void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0;
......@@ -47,6 +49,13 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
set_sigstack(sig_stack, 2 * page_size());
flags = SA_ONSTACK;
}
if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
}
void init_new_thread_signals(int altstack)
{
int flags = altstack ? SA_ONSTACK : 0;
set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
......@@ -61,11 +70,10 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
SA_NOMASK | flags, -1);
if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
signal(SIGCHLD, SIG_IGN);
(void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
signal(SIGHUP, SIG_IGN);
init_irq_signals(sig_stack != NULL);
init_irq_signals(altstack);
}
struct tramp {
......@@ -128,26 +136,6 @@ void trace_myself(void)
panic("ptrace failed in trace_myself");
}
void attach_process(int pid)
{
if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
(ptrace(PTRACE_CONT, pid, 0, 0) < 0))
tracer_panic("OP_FORK failed to attach pid");
wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
tracer_panic("OP_FORK failed to continue process");
}
void tracer_panic(char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
printf("\n");
while(1) sleep(10);
}
void suspend_new_thread(int fd)
{
char c;
......@@ -164,19 +152,18 @@ static int ptrace_child(void *arg)
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
perror("ptrace");
_exit(1);
os_kill_process(pid, 0);
}
os_stop_process(pid);
_exit(os_getpid() == pid);
}
void __init check_ptrace(void)
static int start_ptraced_child(void **stack_out)
{
void *stack;
unsigned long sp;
int status, pid, n, syscall;
int pid, n, status;
printk("Checking that ptrace can change system call numbers...");
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
......@@ -191,6 +178,33 @@ void __init check_ptrace(void)
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("check_ptrace : expected SIGSTOP, got status = %d",
status);
*stack_out = stack;
return(pid);
}
static void stop_ptraced_child(int pid, void *stack, int exitcode)
{
int status, n;
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", errno);
n = waitpid(pid, &status, 0);
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
panic("check_ptrace : child exited with status 0x%x", status);
if(munmap(stack, PAGE_SIZE) < 0)
panic("check_ptrace : munmap failed, errno = %d", errno);
}
void __init check_ptrace(void)
{
void *stack;
int pid, syscall, n, status;
printk("Checking that ptrace can change system call numbers...");
pid = start_ptraced_child(&stack);
while(1){
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d",
......@@ -213,23 +227,19 @@ void __init check_ptrace(void)
break;
}
}
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", errno);
n = waitpid(pid, &status, 0);
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
panic("check_ptrace : child exited with status 0x%x", status);
if(munmap(stack, PAGE_SIZE) < 0)
panic("check_ptrace : munmap failed, errno = %d", errno);
stop_ptraced_child(pid, stack, 0);
printk("OK\n");
}
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
jmp_buf buf;
int n;
*jmp_ptr = &buf;
if(setjmp(buf)) return(1);
n = setjmp(buf);
if(n != 0)
return(n);
(*fn)(arg);
return(0);
}
......@@ -244,6 +254,66 @@ void forward_pending_sigio(int target)
kill(target, SIGIO);
}
#ifdef CONFIG_MODE_SKAS
static void init_registers(int pid)
{
int err;
if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
errno);
err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
if(!err)
return;
have_fpx_regs = 0;
if(errno != EIO)
panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
errno);
err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
if(err)
panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
errno);
}
#endif
int can_do_skas(void)
{
#ifdef CONFIG_MODE_SKAS
struct ptrace_faultinfo fi;
void *stack;
int pid, n, ret = 1;
printk("Checking for the skas3 patch in the host...");
pid = start_ptraced_child(&stack);
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if(n < 0){
if(errno == EIO)
printk("not found\n");
else printk("No (unexpected errno - %d)\n", errno);
ret = 0;
}
else printk("found\n");
init_registers(pid);
stop_ptraced_child(pid, stack, 1);
printk("Checking for /proc/mm...");
if(access("/proc/mm", W_OK)){
printk("not found\n");
ret = 0;
}
else printk("found\n");
return(ret);
#else
return(0);
#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
......
This diff is collapsed.
......@@ -8,6 +8,8 @@
#include "kern_util.h"
#include "kern.h"
#include "os.h"
#include "mode.h"
#include "choose-mode.h"
#ifdef CONFIG_SMP
static void kill_idlers(int me)
......@@ -17,26 +19,17 @@ static void kill_idlers(int me)
for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
p = idle_threads[i];
if((p != NULL) && (p->thread.extern_pid != me))
os_kill_process(p->thread.extern_pid);
if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
os_kill_process(p->thread.mode.tt.extern_pid, 0);
}
}
#endif
static void kill_off_processes(void)
{
struct task_struct *p;
int me;
me = os_getpid();
for_each_process(p){
if(p->thread.extern_pid != me)
os_kill_process(p->thread.extern_pid);
}
if(init_task.thread.extern_pid != me)
os_kill_process(init_task.thread.extern_pid);
CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
#ifdef CONFIG_SMP
kill_idlers(me);
kill_idlers(os_getpid());
#endif
}
......@@ -50,16 +43,14 @@ void machine_restart(char * __unused)
{
do_uml_exitcalls();
kill_off_processes();
tracing_reboot();
os_kill_process(os_getpid());
CHOOSE_MODE(reboot_tt(), reboot_skas());
}
void machine_power_off(void)
{
do_uml_exitcalls();
kill_off_processes();
tracing_halt();
os_kill_process(os_getpid());
CHOOSE_MODE(halt_tt(), halt_skas());
}
void machine_halt(void)
......
......@@ -171,7 +171,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
*/
if((current->ptrace & PT_DTRACE) &&
is_syscall(PT_REGS_IP(&current->thread.regs)))
current->thread.singlestep_syscall = 1;
current->thread.mode.tt.singlestep_syscall = 1;
return(0);
}
......@@ -241,7 +241,7 @@ 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.regs.sc, sc,
copy_sc_from_user(current->thread.regs.regs.mode.tt, sc,
&signal_frame_sc.arch);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
......@@ -257,7 +257,7 @@ int sys_rt_sigreturn(struct pt_regs regs)
sigdelsetmask(&current->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
copy_sc_from_user(current->thread.regs.regs.sc, sc,
copy_sc_from_user(current->thread.regs.regs.mode.tt, sc,
&signal_frame_sc.arch);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
......
......@@ -21,13 +21,12 @@
void set_sigstack(void *sig_stack, int size)
{
stack_t stack;
stack_t stack = ((stack_t) { .ss_flags = 0,
.ss_sp = (__ptr_t) sig_stack,
.ss_size = size - sizeof(void *) });
stack.ss_sp = (__ptr_t) sig_stack;
stack.ss_flags = 0;
stack.ss_size = size - sizeof(void *);
if(sigaltstack(&stack, NULL) != 0)
panic("sigaltstack failed");
panic("enabling signal stack failed, errno = %d\n", errno);
}
void set_handler(int sig, void (*handler)(int), int flags, ...)
......
#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
obj-y = exec_kern.o exec_user.o mem_user.o mmu.o process.o process_kern.o \
syscall_user.o trap_user.o
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
include $(TOPDIR)/Rules.make
include/skas_ptregs.h : util/mk_ptregs
util/mk_ptregs > $@
util/mk_ptregs :
$(MAKE) -C util
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
clean :
$(MAKE) -C util clean
$(RM) -f include/skas_ptregs.h
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/kernel.h"
#include "asm/current.h"
#include "asm/page.h"
#include "asm/signal.h"
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "asm/mmu_context.h"
#include "tlb.h"
#include "skas.h"
#include "mmu.h"
#include "os.h"
void flush_thread_skas(void)
{
force_flush_all();
switch_mm_skas(current->mm->context.skas.mm_fd);
}
void start_thread_skas(struct pt_regs *regs, unsigned long eip,
unsigned long esp)
{
set_fs(USER_DS);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include "user.h"
#include "kern_util.h"
#include "os.h"
#include "time_user.h"
static int user_thread_tramp(void *arg)
{
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
panic("user_thread_tramp - PTRACE_TRACEME failed, "
"errno = %d\n", errno);
enable_timer();
os_stop_process(os_getpid());
return(0);
}
int user_thread(unsigned long stack, int flags)
{
int pid, status;
pid = clone(user_thread_tramp, (void *) stack_sp(stack),
flags | CLONE_FILES | SIGCHLD, NULL);
if(pid < 0){
printk("user_thread - clone failed, errno = %d\n", errno);
return(pid);
}
if(waitpid(pid, &status, WUNTRACED) < 0){
printk("user_thread - waitpid failed, errno = %d\n", errno);
return(-errno);
}
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
printk("user_thread - trampoline didn't stop, status = %d\n",
status);
return(-EINVAL);
}
return(pid);
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_MMU_H
#define __SKAS_MMU_H
#include "linux/list.h"
#include "linux/spinlock.h"
struct mmu_context_skas {
int mm_fd;
};
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __MODE_SKAS_H__
#define __MODE_SKAS_H__
extern unsigned long exec_regs[];
extern unsigned long exec_fp_regs[];
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,
unsigned long fault_addr, int fault_type);
extern void sig_handler_common_skas(int sig, struct sigcontext *sc);
extern void halt_skas(void);
extern void reboot_skas(void);
extern void kill_off_processes_skas(void);
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_MODE_KERN_H__
#define __SKAS_MODE_KERN_H__
#include "linux/sched.h"
#include "asm/page.h"
#include "asm/ptrace.h"
extern void flush_thread_skas(void);
extern void *switch_to_skas(void *prev, void *next);
extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
unsigned long esp);
extern int copy_thread_skas(int nr, unsigned long clone_flags,
unsigned long sp, unsigned long stack_top,
struct task_struct *p, struct pt_regs *regs);
extern void release_thread_skas(struct task_struct *task);
extern void exit_thread_skas(void);
extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
extern void init_idle_skas(void);
extern void flush_tlb_kernel_vm_skas(void);
extern void __flush_tlb_one_skas(unsigned long addr);
extern void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start,
unsigned long end);
extern void flush_tlb_mm_skas(struct mm_struct *mm);
extern void force_flush_all_skas(void);
extern long execute_syscall_skas(void *r);
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 thread_struct *thread);
#define kmem_end_skas (host_task_size)
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_PROC_MM_H
#define __SKAS_PROC_MM_H
#define MM_MMAP 54
#define MM_MUNMAP 55
#define MM_MPROTECT 56
#define MM_COPY_SEGMENTS 57
struct mm_mmap {
unsigned long addr;
unsigned long len;
unsigned long prot;
unsigned long flags;
unsigned long fd;
unsigned long offset;
};
struct mm_munmap {
unsigned long addr;
unsigned long len;
};
struct mm_mprotect {
unsigned long addr;
unsigned long len;
unsigned int prot;
};
struct proc_mm_op {
int op;
union {
struct mm_mmap mmap;
struct mm_munmap munmap;
struct mm_mprotect mprotect;
int copy_segments;
} u;
};
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __PTRACE_SKAS_H
#define __PTRACE_SKAS_H
#include "uml-config.h"
#ifdef CONFIG_MODE_SKAS
#include "skas_ptregs.h"
#define HOST_FRAME_SIZE 17
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
#define REGS_EAX(r) ((r)[HOST_EAX])
#define REGS_EBX(r) ((r)[HOST_EBX])
#define REGS_ECX(r) ((r)[HOST_ECX])
#define REGS_EDX(r) ((r)[HOST_EDX])
#define REGS_ESI(r) ((r)[HOST_ESI])
#define REGS_EDI(r) ((r)[HOST_EDI])
#define REGS_EBP(r) ((r)[HOST_EBP])
#define REGS_CS(r) ((r)[HOST_CS])
#define REGS_SS(r) ((r)[HOST_SS])
#define REGS_DS(r) ((r)[HOST_DS])
#define REGS_ES(r) ((r)[HOST_ES])
#define REGS_FS(r) ((r)[HOST_FS])
#define REGS_GS(r) ((r)[HOST_GS])
#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
#endif
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_H
#define __SKAS_H
#include "sysdep/ptrace.h"
extern int userspace_pid;
extern void switch_threads(void *me, void *next);
extern void thread_wait(void *sw, void *fb);
extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int));
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 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 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 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 start_userspace(void);
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_PTRACE_H
#define __SKAS_PTRACE_H
struct ptrace_faultinfo {
int is_write;
unsigned long addr;
};
struct ptrace_ldt {
int func;
void *ptr;
unsigned long bytecount;
};
#define PTRACE_FAULTINFO 52
#define PTRACE_SIGPENDING 53
#define PTRACE_LDT 54
#define PTRACE_SWITCH_MM 55
#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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <errno.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include "mem_user.h"
#include "user.h"
#include "os.h"
#include "proc_mm.h"
void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
int r, int w, int x)
{
struct proc_mm_op map;
struct mem_region *region;
int prot, n;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
region = phys_region(phys);
map = ((struct proc_mm_op) { .op = MM_MMAP,
.u =
{ .mmap =
{ .addr = virt,
.len = len,
.prot = prot,
.flags = MAP_SHARED |
MAP_FIXED,
.fd = region->fd,
.offset = phys_offset(phys)
} } } );
n = os_write_file(fd, (char *) &map, sizeof(map));
if(n != sizeof(map))
printk("map : /proc/mm map failed, errno = %d\n", errno);
}
int unmap(int fd, void *addr, int len)
{
struct proc_mm_op unmap;
int n;
unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
.u =
{ .munmap =
{ .addr = (unsigned long) addr,
.len = len } } } );
n = os_write_file(fd, (char *) &unmap, sizeof(unmap));
if((n != 0) && (n != sizeof(unmap)))
return(-errno);
return(0);
}
int protect(int fd, unsigned long addr, unsigned long len, int r, int w,
int x, int must_succeed)
{
struct proc_mm_op protect;
int prot, n;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
.u =
{ .mprotect =
{ .addr = (unsigned long) addr,
.len = len,
.prot = prot } } } );
n = os_write_file(fd, (char *) &protect, sizeof(protect));
if((n != 0) && (n != sizeof(protect))){
if(must_succeed)
panic("protect failed, errno = %d", errno);
return(-errno);
}
return(0);
}
void before_mem_skas(unsigned long unused)
{
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/sched.h"
#include "linux/list.h"
#include "linux/spinlock.h"
#include "linux/slab.h"
#include "asm/current.h"
#include "asm/segment.h"
#include "asm/mmu.h"
#include "os.h"
#include "skas.h"
int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
{
int from;
if((current->mm != NULL) && (current->mm != &init_mm))
from = current->mm->context.skas.mm_fd;
else from = -1;
mm->context.skas.mm_fd = new_mm(from);
if(mm->context.skas.mm_fd < 0)
panic("init_new_context_skas - new_mm failed, errno = %d\n",
mm->context.skas.mm_fd);
return(0);
}
void destroy_context_skas(struct mm_struct *mm)
{
os_close_file(mm->context.skas.mm_fd);
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <asm/unistd.h>
#include "user.h"
#include "ptrace_user.h"
#include "time_user.h"
#include "sysdep/ptrace.h"
#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"
unsigned long exec_regs[FRAME_SIZE];
unsigned long exec_fp_regs[HOST_FP_SIZE];
unsigned long exec_fpx_regs[HOST_XFP_SIZE];
int have_fpx_regs = 1;
static void handle_segv(int pid)
{
struct ptrace_faultinfo fault;
int err;
err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault);
if(err)
panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n",
errno);
segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
}
static void handle_trap(int pid, struct uml_pt_regs *regs)
{
int err, syscall_nr, status;
syscall_nr = PT_SYSCALL_NR(regs->mode.skas.regs);
if(syscall_nr < 1){
relay_signal(SIGTRAP, regs);
return;
}
UPT_SYSCALL_NR(regs) = syscall_nr;
err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
if(err < 0)
panic("handle_trap - nullifying syscall failed errno = %d\n",
errno);
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
if(err < 0)
panic("handle_trap - continuing to end of syscall failed, "
"errno = %d\n", errno);
err = waitpid(pid, &status, WUNTRACED);
if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
panic("handle_trap - failed to wait at end of syscall, "
"errno = %d, status = %d\n", errno, status);
handle_syscall(regs);
}
int userspace_pid;
static int userspace_tramp(void *arg)
{
init_new_thread_signals(0);
enable_timer();
ptrace(PTRACE_TRACEME, 0, 0, 0);
os_stop_process(os_getpid());
}
void start_userspace(void)
{
void *stack;
unsigned long sp;
int pid, status, n;
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
panic("start_userspace : mmap failed, errno = %d", errno);
sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
pid = clone(userspace_tramp, (void *) sp,
CLONE_FILES | CLONE_VM | SIGCHLD, NULL);
if(pid < 0)
panic("start_userspace : clone failed, errno = %d", errno);
do {
n = waitpid(pid, &status, WUNTRACED);
if(n < 0)
panic("start_userspace : wait failed, errno = %d",
errno);
} while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("start_userspace : expected SIGSTOP, got status = %d",
status);
if(munmap(stack, PAGE_SIZE) < 0)
panic("start_userspace : munmap failed, errno = %d\n", errno);
userspace_pid = pid;
}
void userspace(struct uml_pt_regs *regs)
{
int err, status, op;
restore_registers(regs);
err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
errno);
while(1){
err = waitpid(userspace_pid, &status, WUNTRACED);
if(err < 0)
panic("userspace - waitpid failed, errno = %d\n",
errno);
regs->is_user = 1;
save_registers(regs);
if(WIFSTOPPED(status)){
switch(WSTOPSIG(status)){
case SIGSEGV:
handle_segv(userspace_pid);
break;
case SIGTRAP:
handle_trap(userspace_pid, regs);
break;
case SIGIO:
case SIGVTALRM:
case SIGILL:
case SIGBUS:
case SIGFPE:
user_signal(WSTOPSIG(status), regs);
break;
default:
printk("userspace - child stopped with signal "
"%d\n", WSTOPSIG(status));
}
interrupt_end();
}
restore_registers(regs);
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSCALL;
err = ptrace(op, userspace_pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, "
"errno = %d\n", errno);
}
}
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
jmp_buf switch_buf, fork_buf;
*switch_buf_ptr = &switch_buf;
*fork_buf_ptr = &fork_buf;
if(setjmp(fork_buf) == 0)
new_thread_proc(stack, handler);
remove_sigstack();
}
void thread_wait(void *sw, void *fb)
{
jmp_buf buf, **switch_buf = sw, *fork_buf;
*switch_buf = &buf;
fork_buf = fb;
if(setjmp(buf) == 0)
longjmp(*fork_buf, 1);
}
static int move_registers(int int_op, int fp_op, struct uml_pt_regs *regs,
unsigned long *fp_regs)
{
if(ptrace(int_op, userspace_pid, 0, regs->mode.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)
{
unsigned long *fp_regs;
int err, fp_op;
if(have_fpx_regs){
fp_op = PTRACE_GETFPXREGS;
fp_regs = regs->mode.skas.xfp;
}
else {
fp_op = PTRACE_GETFPREGS;
fp_regs = regs->mode.skas.fp;
}
err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
if(err)
panic("save_registers - saving registers failed, errno = %d\n",
err);
}
void restore_registers(struct 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;
}
else {
fp_op = PTRACE_SETFPREGS;
fp_regs = regs->mode.skas.fp;
}
err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
if(err)
panic("restore_registers - saving registers failed, "
"errno = %d\n", err);
}
void switch_threads(void *me, void *next)
{
jmp_buf my_buf, **me_ptr = me, *next_buf = next;
*me_ptr = &my_buf;
if(setjmp(my_buf) == 0)
longjmp(*next_buf, 1);
}
static jmp_buf initial_jmpbuf;
/* XXX Make these percpu */
static void (*cb_proc)(void *arg);
static void *cb_arg;
static jmp_buf *cb_back;
int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
{
jmp_buf **switch_buf = switch_buf_ptr;
int n;
*fork_buf_ptr = &initial_jmpbuf;
n = setjmp(initial_jmpbuf);
if(n == 0)
new_thread_proc((void *) stack, new_thread_handler);
else if(n == 1)
remove_sigstack();
else if(n == 2){
(*cb_proc)(cb_arg);
longjmp(*cb_back, 1);
}
else if(n == 3)
return(0);
else if(n == 4)
return(1);
longjmp(**switch_buf, 1);
}
void remove_sigstack(void)
{
stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
.ss_sp = NULL,
.ss_size = 0 });
if(sigaltstack(&stack, NULL) != 0)
panic("disabling signal stack failed, errno = %d\n", errno);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
jmp_buf here;
cb_proc = proc;
cb_arg = arg;
cb_back = &here;
if(setjmp(here) == 0)
longjmp(initial_jmpbuf, 2);
}
void halt_skas(void)
{
block_signals();
longjmp(initial_jmpbuf, 3);
}
void reboot_skas(void)
{
block_signals();
longjmp(initial_jmpbuf, 4);
}
int new_mm(int from)
{
struct proc_mm_op copy;
int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
if(fd < 0)
return(-errno);
if(from != -1){
copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
.u =
{ .copy_segments = from } } );
n = os_write_file(fd, (char *) &copy, sizeof(copy));
if(n != sizeof(copy))
printk("new_mm : /proc/mm copy_segments failed, "
"errno = %d\n", errno);
}
return(fd);
}
void switch_mm_skas(int mm_fd)
{
int err;
err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
if(err)
panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
errno);
}
void kill_off_processes_skas(void)
{
os_kill_process(userspace_pid, 1);
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/sched.h"
#include "linux/slab.h"
#include "kern_util.h"
#include "time_user.h"
#include "signal_user.h"
#include "skas.h"
#include "os.h"
#include "user_util.h"
#include "tlb.h"
#include "frame.h"
#include "kern.h"
#include "mode.h"
int singlestepping_skas(void)
{
int ret = current->ptrace & PT_DTRACE;
current->ptrace &= ~PT_DTRACE;
return(ret);
}
void *switch_to_skas(void *prev, void *next)
{
struct task_struct *from, *to;
from = prev;
to = next;
/* XXX need to check runqueues[cpu].idle */
if(current->pid == 0)
switch_timers(0);
to->thread.prev_sched = from;
set_current(to);
switch_threads(&from->thread.mode.skas.switch_buf,
to->thread.mode.skas.switch_buf);
if(current->pid == 0)
switch_timers(1);
return(current->thread.prev_sched);
}
extern void schedule_tail(struct task_struct *prev);
void new_thread_handler(int sig)
{
int (*fn)(void *), n;
void *arg;
fn = current->thread.request.u.thread.proc;
arg = current->thread.request.u.thread.arg;
change_sig(SIGUSR1, 1);
thread_wait(&current->thread.mode.skas.switch_buf,
current->thread.mode.skas.fork_buf);
#ifdef CONFIG_SMP
schedule_tail(NULL);
#endif
current->thread.prev_sched = NULL;
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);
}
void new_thread_proc(void *stack, void (*handler)(int sig))
{
init_new_thread_stack(stack, handler);
os_usr1_process(os_getpid());
}
void release_thread_skas(struct task_struct *task)
{
}
void exit_thread_skas(void)
{
}
void fork_handler(int sig)
{
change_sig(SIGUSR1, 1);
thread_wait(&current->thread.mode.skas.switch_buf,
current->thread.mode.skas.fork_buf);
force_flush_all();
#ifdef CONFIG_SMP
schedule_tail(current->thread.prev_sched);
#endif
current->thread.prev_sched = NULL;
unblock_signals();
userspace(&current->thread.regs.regs);
}
int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
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;
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));
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
new_thread((void *) p->thread.kernel_stack,
&p->thread.mode.skas.switch_buf,
&p->thread.mode.skas.fork_buf, handler);
return(0);
}
void init_idle_skas(void)
{
cpu_tasks[current->thread_info->cpu].pid = os_getpid();
}
extern void start_kernel(void);
static int start_kernel_proc(void *unused)
{
int pid;
block_signals();
pid = os_getpid();
cpu_tasks[0].pid = pid;
cpu_tasks[0].task = current;
#ifdef CONFIG_SMP
cpu_online_map = 1;
#endif
start_kernel();
return(0);
}
int start_uml_skas(void)
{
start_userspace();
capture_signal_stack();
init_new_thread_signals(1);
idle_timer();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
return(start_idle_thread((void *) init_task.thread.kernel_stack,
&init_task.thread.mode.skas.switch_buf,
&init_task.thread.mode.skas.fork_buf));
}
int external_pid_skas(struct task_struct *task)
{
return(userspace_pid);
}
int thread_pid_skas(struct thread_struct *thread)
{
return(userspace_pid);
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <stdlib.h>
#include <signal.h>
#include "kern_util.h"
#include "syscall_user.h"
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
/* XXX Bogus */
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
void handle_syscall(struct 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);
if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
(result == -ERESTARTNOINTR))
do_signal(result);
syscall_trace();
record_syscall_end(index, result);
}
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <signal.h>
#include <errno.h>
#include <asm/sigcontext.h>
#include "sysdep/ptrace.h"
#include "signal_user.h"
#include "user_util.h"
#include "kern_util.h"
#include "task.h"
#include "sigcontext.h"
void sig_handler_common_skas(int sig, struct sigcontext *sc)
{
struct uml_pt_regs save_regs, *r;
struct signal_info *info;
int save_errno = errno;
r = (struct uml_pt_regs *) TASK_REGS(get_current());
save_regs = *r;
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);
change_sig(SIGUSR1, 1);
info = &sig_info[sig];
if(!info->is_irq) unblock_signals();
(*info->handler)(sig, r);
*r = save_regs;
errno = save_errno;
}
extern int missed_ticks[];
void user_signal(int sig, struct 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;
info = &sig_info[sig];
(*info->handler)(sig, regs);
}
/*
* 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:
*/
all: mk_ptregs
mk_ptregs : mk_ptregs.o
$(CC) -o mk_ptregs mk_ptregs.o
mk_ptregs.o : mk_ptregs.c
$(CC) -c $<
clean :
$(RM) -f mk_ptregs *.o *~
#include <asm/ptrace.h>
#include <asm/user.h>
#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val))
int main(int argc, char **argv)
{
printf("/* Automatically generated by "
"arch/um/kernel/skas/util/mk_ptregs */\n");
printf("\n");
printf("#ifndef __SKAS_PT_REGS_\n");
printf("#define __SKAS_PT_REGS_\n");
printf("\n");
printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
printf("#define HOST_FP_SIZE %d\n",
sizeof(struct user_i387_struct) / sizeof(unsigned long));
printf("#define HOST_XFP_SIZE %d\n",
sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
PRINT_REG("IP", EIP);
PRINT_REG("SP", UESP);
PRINT_REG("EFLAGS", EFL);
PRINT_REG("EAX", EAX);
PRINT_REG("EBX", EBX);
PRINT_REG("ECX", ECX);
PRINT_REG("EDX", EDX);
PRINT_REG("ESI", ESI);
PRINT_REG("EDI", EDI);
PRINT_REG("EBP", EBP);
PRINT_REG("CS", CS);
PRINT_REG("SS", SS);
PRINT_REG("DS", DS);
PRINT_REG("FS", FS);
PRINT_REG("ES", ES);
PRINT_REG("GS", GS);
printf("\n");
printf("#endif\n");
return(0);
}
/*
* 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:
*/
......@@ -407,8 +407,8 @@ long execute_syscall(void *r)
set_fs(USER_DS);
if(current->thread.singlestep_syscall){
current->thread.singlestep_syscall = 0;
if(current->thread.mode.tt.singlestep_syscall){
current->thread.mode.tt.singlestep_syscall = 0;
current->ptrace &= ~PT_DTRACE;
force_sig(SIGTRAP, current);
}
......
/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
/* XXX FIXME : Ensure that SIGIO and SIGVTALRM can't happen immediately
* after setting up syscall stack
* block SIGVTALRM in any code that's under wait_for_stop
*/
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <asm/unistd.h>
#include "sysdep/ptrace.h"
#include "sigcontext.h"
#include "ptrace_user.h"
#include "task.h"
#include "user_util.h"
#include "kern_util.h"
/* XXX Bogus */
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
#include "syscall_user.h"
struct {
int syscall;
......@@ -34,67 +16,24 @@ struct {
struct timeval end;
} syscall_record[1024];
void syscall_handler(int sig, struct uml_pt_regs *regs)
int record_syscall_start(int syscall)
{
void *sc;
long result;
int index, max, syscall;
int max, index;
max = sizeof(syscall_record)/sizeof(syscall_record[0]);
index = next_syscall_index(max);
syscall = regs->syscall;
sc = regs->sc;
sc_to_regs(regs, sc, syscall);
SC_START_SYSCALL(sc);
syscall_record[index].syscall = syscall;
syscall_record[index].pid = current_pid();
syscall_record[index].result = 0xdeadbeef;
gettimeofday(&syscall_record[index].start, NULL);
syscall_trace();
result = execute_syscall(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->sc = sc;
SC_SET_SYSCALL_RETURN(sc, result);
if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
(result == -ERESTARTNOINTR))
do_signal(result);
syscall_trace();
syscall_record[index].result = result;
gettimeofday(&syscall_record[index].end, NULL);
return(index);
}
int do_syscall(void *task, int pid)
void record_syscall_end(int index, int result)
{
unsigned long proc_regs[FRAME_SIZE];
struct uml_pt_regs *regs;
int syscall;
if(ptrace_getregs(pid, proc_regs) < 0)
tracer_panic("Couldn't read registers");
syscall = PT_SYSCALL_NR(proc_regs);
regs = TASK_REGS(task);
UPT_SYSCALL_NR(regs) = syscall;
if(syscall < 1) return(0);
if((syscall != __NR_sigreturn) &&
((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
((unsigned long *) PT_IP(proc_regs) <= &_etext))
tracer_panic("I'm tracing myself and I can't get out");
if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid) < 0)
tracer_panic("do_syscall : Nullifying syscall failed, "
"errno = %d", errno);
return(1);
syscall_record[index].result = result;
gettimeofday(&syscall_record[index].end, NULL);
}
/*
......
......@@ -30,8 +30,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long addr;
int r, w, x, err;
if((current->thread.extern_pid != -1) &&
(current->thread.extern_pid != os_getpid()))
if((current->thread.mode.tt.extern_pid != -1) &&
(current->thread.mode.tt.extern_pid != os_getpid()))
panic("fix_range fixing wrong address space, current = 0x%p",
current);
if(mm == NULL) return;
......@@ -60,23 +60,25 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
w = 0;
}
if(force || pte_newpage(*npte)){
err = unmap((void *) addr, PAGE_SIZE);
err = os_unmap_memory((void *) addr,
PAGE_SIZE);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
if(pte_present(*npte))
map(addr, pte_val(*npte) & PAGE_MASK,
map_memory(addr,
pte_val(*npte) & PAGE_MASK,
PAGE_SIZE, r, w, x);
}
else if(pte_newprot(*npte)){
protect(addr, PAGE_SIZE, r, w, x, 1);
protect_memory(addr, PAGE_SIZE, r, w, x, 1);
}
*npte = pte_mkuptodate(*npte);
addr += PAGE_SIZE;
}
else {
if(force || pmd_newpage(*npmd)){
err = unmap((void *) addr, PMD_SIZE);
err = os_unmap_memory((void *) addr, PMD_SIZE);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
......@@ -106,24 +108,26 @@ void flush_kernel_range(unsigned long start, unsigned long end, int update_seq)
pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte) || pte_newpage(*pte)){
updated = 1;
err = unmap((void *) addr, PAGE_SIZE);
err = os_unmap_memory((void *) addr,
PAGE_SIZE);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
if(pte_present(*pte))
map(addr, pte_val(*pte) & PAGE_MASK,
map_memory(addr,
pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, 1, 1, 1);
}
else if(pte_newprot(*pte)){
updated = 1;
protect(addr, PAGE_SIZE, 1, 1, 1, 1);
protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
}
addr += PAGE_SIZE;
}
else {
if(pmd_newpage(*pmd)){
updated = 1;
err = unmap((void *) addr, PMD_SIZE);
err = os_unmap_memory((void *) addr, PMD_SIZE);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
......@@ -143,7 +147,7 @@ static void protect_vm_page(unsigned long addr, int w, int must_succeed)
{
int err;
err = protect(addr, PAGE_SIZE, 1, w, 1, must_succeed);
err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed);
if(err == 0) return;
else if((err == -EFAULT) || (err == -ENOMEM)){
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
......@@ -207,8 +211,8 @@ void flush_tlb_mm(struct mm_struct *mm)
fix_range(mm, 0, STACK_TOP, 0);
seq = atomic_read(&vmchange_seq);
if(current->thread.vm_seq == seq) return;
current->thread.vm_seq = seq;
if(current->thread.mode.tt.vm_seq == seq) return;
current->thread.mode.tt.vm_seq = seq;
flush_kernel_range(start_vm, end_vm, 0);
}
......
......@@ -117,7 +117,7 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
if(catcher != NULL){
current->thread.fault_addr = (void *) address;
up_read(&mm->mmap_sem);
do_longjmp(catcher);
do_longjmp(catcher, 1);
}
else if(current->thread.fault_addr != NULL){
panic("fault_addr set but no fault catcher");
......@@ -161,7 +161,7 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
void bus_handler(int sig, struct uml_pt_regs *regs)
{
if(current->thread.fault_catcher != NULL)
do_longjmp(current->thread.fault_catcher);
do_longjmp(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
......@@ -185,250 +185,6 @@ int next_trap_index(int limit)
return(ret);
}
extern int debugger_pid;
extern int debugger_fd;
extern int debugger_parent;
#ifdef CONFIG_PT_PROXY
int debugger_signal(int status, pid_t pid)
{
return(debugger_proxy(status, pid));
}
void child_signal(pid_t pid, int status)
{
child_proxy(pid, status);
}
static void gdb_announce(char *dev_name, int dev)
{
printf("gdb assigned device '%s'\n", dev_name);
}
static struct chan_opts opts = {
announce : gdb_announce,
xterm_title : "UML kernel debugger",
raw : 0,
tramp_stack : 0,
in_kernel : 0,
};
/* Accessed by the tracing thread, which automatically serializes access */
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 void xterm_close(int, void *);
int open_gdb_chan(void)
{
char stack[PAGE_SIZE];
opts.tramp_stack = (unsigned long) stack;
xterm_data = xterm_init("", 0, &opts);
xterm_fd = xterm_open(1, 1, 1, xterm_data);
return(xterm_fd);
}
static void exit_debugger_cb(void *unused)
{
if(debugger_pid != -1){
if(gdb_pid != -1){
fake_child_exit();
gdb_pid = -1;
}
else kill_child_dead(debugger_pid);
debugger_pid = -1;
if(debugger_parent != -1)
detach(debugger_parent, SIGINT);
}
if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
}
static void exit_debugger(void)
{
tracing_cb(exit_debugger_cb, NULL);
}
__uml_exitcall(exit_debugger);
struct gdb_data {
char *str;
int err;
};
static void config_gdb_cb(void *arg)
{
struct gdb_data *data = arg;
struct task_struct *task;
int pid;
data->err = -1;
if(debugger_pid != -1) exit_debugger_cb(NULL);
if(!strncmp(data->str, "pid,", strlen("pid,"))){
data->str += strlen("pid,");
pid = simple_strtoul(data->str, NULL, 0);
task = cpu_tasks[0].task;
debugger_pid = attach_debugger(task->thread.extern_pid,
pid, 0);
if(debugger_pid != -1){
data->err = 0;
gdb_pid = pid;
}
return;
}
data->err = 0;
debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
init_proxy(debugger_pid, 0, 0);
}
int gdb_config(char *str)
{
struct gdb_data data;
if(*str++ != '=') return(-1);
data.str = str;
tracing_cb(config_gdb_cb, &data);
return(data.err);
}
void remove_gdb_cb(void *unused)
{
exit_debugger_cb(NULL);
}
int gdb_remove(char *unused)
{
tracing_cb(remove_gdb_cb, NULL);
return(0);
}
#ifdef CONFIG_MCONSOLE
static struct mc_device gdb_mc = {
name: "gdb",
config: gdb_config,
remove: gdb_remove,
};
int gdb_mc_init(void)
{
mconsole_register_dev(&gdb_mc);
return(0);
}
__initcall(gdb_mc_init);
#endif
void signal_usr1(int sig)
{
if(debugger_pid != -1){
printk(KERN_ERR "The debugger is already running\n");
return;
}
debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
init_proxy(debugger_pid, 0, 0);
}
int init_ptrace_proxy(int idle_pid, int startup, int stop)
{
int pid, status;
pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
if(pid < 0){
cont(idle_pid);
return(-1);
}
init_proxy(pid, 1, status);
return(pid);
}
int attach_debugger(int idle_pid, int pid, int stop)
{
int status = 0, err;
err = attach(pid);
if(err < 0){
printf("Failed to attach pid %d, errno = %d\n", pid, -err);
return(-1);
}
if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
init_proxy(pid, 1, status);
return(pid);
}
#ifdef notdef /* Put this back in when it does something useful */
static int __init uml_gdb_init_setup(char *line, int *add)
{
gdb_init = uml_strdup(line);
return 0;
}
__uml_setup("gdb=", uml_gdb_init_setup,
"gdb=<channel description>\n\n"
);
#endif
static int __init uml_gdb_pid_setup(char *line, int *add)
{
gdb_pid = simple_strtoul(line, NULL, 0);
*add = 0;
return 0;
}
__uml_setup("gdb-pid=", uml_gdb_pid_setup,
"gdb-pid=<pid>\n"
" gdb-pid is used to attach an external debugger to UML. This may be\n"
" an already-running gdb or a debugger-like process like strace.\n\n"
);
#else
int debugger_signal(int status, pid_t pid){ return(0); }
void child_signal(pid_t pid, int status){ }
int init_ptrace_proxy(int idle_pid, int startup, int stop)
{
printk(KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
kill_child_dead(idle_pid);
exit(1);
}
void signal_usr1(int sig)
{
printk(KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
}
int attach_debugger(int idle_pid, int pid, int stop)
{
printk(KERN_ERR "attach_debugger called when CONFIG_PT_PROXY "
"is off\n");
return(-1);
}
int config_gdb(char *str)
{
return(-1);
}
int remove_gdb(void)
{
return(-1);
}
int init_parent_proxy(int pid)
{
return(-1);
}
void debugger_parent_signal(int status, int pid)
{
}
#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
......
This diff is collapsed.
#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
obj-y = exec_kern.o exec_user.o gdb.o gdb_kern.o mem.o process_kern.o \
syscall_user.o tracer.o
obj-$(CONFIG_PT_PROXY) += ptproxy/
USER_OBJS := $(filter %_user.o,$(obj-y)) gdb.o tracer.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
include $(TOPDIR)/Rules.make
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
clean :
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/init.h"
#include "linux/config.h"
#include "mconsole_kern.h"
#ifdef CONFIG_MCONSOLE
extern int gdb_config(char *str);
extern int gdb_remove(char *unused);
static struct mc_device gdb_mc = {
name: "gdb",
config: gdb_config,
remove: gdb_remove,
};
int gdb_mc_init(void)
{
mconsole_register_dev(&gdb_mc);
return(0);
}
__initcall(gdb_mc_init);
#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:
*/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -35,7 +35,7 @@ int get_pty(void)
}
info.fd = fd;
tracing_cb(grantpt_cb, &info);
initial_thread_cb(grantpt_cb, &info);
if(info.res < 0){
printk("get_pty : Couldn't grant pty - errno = %d\n",
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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