uml: style fixes pass 3
Formatting changes in the files which have been changed in the course of folding foo_skas functions into their callers. These include: copyright updates header file trimming style fixes adding severity to printks These changes should be entirely non-functional. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
77bf440031
commit
ba180fd437
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __IRQ_USER_H__
|
#ifndef __IRQ_USER_H__
|
||||||
#define __IRQ_USER_H__
|
#define __IRQ_USER_H__
|
||||||
|
|
||||||
#include "uml-config.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
|
||||||
struct irq_fd {
|
struct irq_fd {
|
||||||
struct irq_fd *next;
|
struct irq_fd *next;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
#include "sysdep/faultinfo.h"
|
#include "sysdep/faultinfo.h"
|
||||||
#include "uml-config.h"
|
|
||||||
|
|
||||||
typedef void (*kern_hndl)(int, struct uml_pt_regs *);
|
typedef void (*kern_hndl)(int, struct uml_pt_regs *);
|
||||||
|
|
||||||
|
@@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __OS_H__
|
#ifndef __OS_H__
|
||||||
#define __OS_H__
|
#define __OS_H__
|
||||||
|
|
||||||
#include "uml-config.h"
|
#include <stdarg.h>
|
||||||
#include "asm/types.h"
|
|
||||||
#include "../os/include/file.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "skas/mm_id.h"
|
|
||||||
#include "irq_user.h"
|
#include "irq_user.h"
|
||||||
|
#include "kern_util.h"
|
||||||
|
#include "longjmp.h"
|
||||||
|
#include "mm_id.h"
|
||||||
#include "sysdep/tls.h"
|
#include "sysdep/tls.h"
|
||||||
#include "sysdep/archsetjmp.h"
|
#include "../os/include/file.h"
|
||||||
|
|
||||||
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
|
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
|
||||||
|
|
||||||
@@ -140,7 +138,7 @@ extern int os_set_slip(int fd);
|
|||||||
extern int os_set_owner(int fd, int pid);
|
extern int os_set_owner(int fd, int pid);
|
||||||
extern int os_mode_fd(int fd, int mode);
|
extern int os_mode_fd(int fd, int mode);
|
||||||
|
|
||||||
extern int os_seek_file(int fd, __u64 offset);
|
extern int os_seek_file(int fd, unsigned long long offset);
|
||||||
extern int os_open_file(char *file, struct openflags flags, int mode);
|
extern int os_open_file(char *file, struct openflags flags, int mode);
|
||||||
extern int os_read_file(int fd, void *buf, int len);
|
extern int os_read_file(int fd, void *buf, int len);
|
||||||
extern int os_write_file(int fd, const void *buf, int count);
|
extern int os_write_file(int fd, const void *buf, int count);
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SKAS_H
|
#ifndef __SKAS_H
|
||||||
#define __SKAS_H
|
#define __SKAS_H
|
||||||
|
|
||||||
#include "mm_id.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
|
||||||
extern int userspace_pid[];
|
extern int userspace_pid[];
|
||||||
|
@@ -1,24 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/slab.h"
|
#include "linux/stddef.h"
|
||||||
|
#include "linux/fs.h"
|
||||||
#include "linux/smp_lock.h"
|
#include "linux/smp_lock.h"
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
#include "linux/fs.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/ptrace.h"
|
#include "asm/current.h"
|
||||||
#include "asm/pgtable.h"
|
#include "asm/processor.h"
|
||||||
#include "asm/tlbflush.h"
|
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "kern_util.h"
|
|
||||||
#include "as-layout.h"
|
|
||||||
#include "mem_user.h"
|
#include "mem_user.h"
|
||||||
#include "kern.h"
|
#include "skas.h"
|
||||||
#include "irq_user.h"
|
|
||||||
#include "tlb.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas/skas.h"
|
|
||||||
|
|
||||||
void flush_thread(void)
|
void flush_thread(void)
|
||||||
{
|
{
|
||||||
@@ -30,7 +25,7 @@ void flush_thread(void)
|
|||||||
|
|
||||||
ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data);
|
ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("flush_thread - clearing address space failed, "
|
printk(KERN_ERR "flush_thread - clearing address space failed, "
|
||||||
"err = %d\n", ret);
|
"err = %d\n", ret);
|
||||||
force_sig(SIGKILL, current);
|
force_sig(SIGKILL, current);
|
||||||
}
|
}
|
||||||
@@ -71,7 +66,7 @@ static long execve1(char *file, char __user * __user *argv,
|
|||||||
#endif
|
#endif
|
||||||
task_unlock(current);
|
task_unlock(current);
|
||||||
}
|
}
|
||||||
return(error);
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
|
long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
|
||||||
@@ -81,7 +76,7 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
|
|||||||
err = execve1(file, argv, env);
|
err = execve1(file, argv, env);
|
||||||
if (!err)
|
if (!err)
|
||||||
do_longjmp(current->thread.exec_buf, 1);
|
do_longjmp(current->thread.exec_buf, 1);
|
||||||
return(err);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_execve(char __user *file, char __user *__user *argv,
|
long sys_execve(char __user *file, char __user *__user *argv,
|
||||||
@@ -98,5 +93,5 @@ long sys_execve(char __user *file, char __user *__user *argv,
|
|||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
return(error);
|
return error;
|
||||||
}
|
}
|
||||||
|
@@ -1,37 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
* Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
|
* Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
|
||||||
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
|
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/kernel.h"
|
#include "linux/cpumask.h"
|
||||||
#include "linux/module.h"
|
|
||||||
#include "linux/smp.h"
|
|
||||||
#include "linux/kernel_stat.h"
|
|
||||||
#include "linux/interrupt.h"
|
|
||||||
#include "linux/random.h"
|
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/file.h"
|
|
||||||
#include "linux/proc_fs.h"
|
|
||||||
#include "linux/init.h"
|
|
||||||
#include "linux/seq_file.h"
|
|
||||||
#include "linux/profile.h"
|
|
||||||
#include "linux/hardirq.h"
|
#include "linux/hardirq.h"
|
||||||
#include "asm/irq.h"
|
#include "linux/interrupt.h"
|
||||||
#include "asm/hw_irq.h"
|
#include "linux/kernel_stat.h"
|
||||||
#include "asm/atomic.h"
|
#include "linux/module.h"
|
||||||
#include "asm/signal.h"
|
#include "linux/seq_file.h"
|
||||||
#include "asm/system.h"
|
|
||||||
#include "asm/errno.h"
|
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "irq_user.h"
|
|
||||||
#include "irq_kern.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "sigio.h"
|
|
||||||
#include "misc_constants.h"
|
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
|
#include "kern_util.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic, controller-independent functions:
|
* Generic, controller-independent functions:
|
||||||
@@ -71,9 +53,8 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||||||
seq_putc(p, '\n');
|
seq_putc(p, '\n');
|
||||||
skip:
|
skip:
|
||||||
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
|
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
|
||||||
} else if (i == NR_IRQS) {
|
} else if (i == NR_IRQS)
|
||||||
seq_putc(p, '\n');
|
seq_putc(p, '\n');
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -102,11 +83,13 @@ void sigio_handler(int sig, struct uml_pt_regs *regs)
|
|||||||
while (1) {
|
while (1) {
|
||||||
n = os_waiting_for_events(active_fds);
|
n = os_waiting_for_events(active_fds);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
if(n == -EINTR) continue;
|
if (n == -EINTR)
|
||||||
|
continue;
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
|
for (irq_fd = active_fds; irq_fd != NULL;
|
||||||
|
irq_fd = irq_fd->next) {
|
||||||
if (irq_fd->current_events != 0) {
|
if (irq_fd->current_events != 0) {
|
||||||
irq_fd->current_events = 0;
|
irq_fd->current_events = 0;
|
||||||
do_IRQ(irq_fd->irq, regs);
|
do_IRQ(irq_fd->irq, regs);
|
||||||
@@ -138,8 +121,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
|
|||||||
|
|
||||||
if (type == IRQ_READ)
|
if (type == IRQ_READ)
|
||||||
events = UM_POLLIN | UM_POLLPRI;
|
events = UM_POLLIN | UM_POLLPRI;
|
||||||
else
|
else events = UM_POLLOUT;
|
||||||
events = UM_POLLOUT;
|
|
||||||
*new_fd = ((struct irq_fd) { .next = NULL,
|
*new_fd = ((struct irq_fd) { .next = NULL,
|
||||||
.id = dev_id,
|
.id = dev_id,
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
@@ -153,9 +135,10 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
|
|||||||
spin_lock_irqsave(&irq_lock, flags);
|
spin_lock_irqsave(&irq_lock, flags);
|
||||||
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
|
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
|
||||||
if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
|
if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
|
||||||
printk("Registering fd %d twice\n", fd);
|
printk(KERN_ERR "Registering fd %d twice\n", fd);
|
||||||
printk("Irqs : %d, %d\n", irq_fd->irq, irq);
|
printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq);
|
||||||
printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
|
printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id,
|
||||||
|
dev_id);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +154,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* n > 0
|
/*
|
||||||
|
* n > 0
|
||||||
* It means we couldn't put new pollfd to current pollfds
|
* It means we couldn't put new pollfd to current pollfds
|
||||||
* and tmp_fds is NULL or too small for new pollfds array.
|
* and tmp_fds is NULL or too small for new pollfds array.
|
||||||
* Needed size is equal to n as minimum.
|
* Needed size is equal to n as minimum.
|
||||||
@@ -197,7 +181,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&irq_lock, flags);
|
spin_unlock_irqrestore(&irq_lock, flags);
|
||||||
|
|
||||||
/* This calls activate_fd, so it has to be outside the critical
|
/*
|
||||||
|
* This calls activate_fd, so it has to be outside the critical
|
||||||
* section.
|
* section.
|
||||||
*/
|
*/
|
||||||
maybe_sigio_broken(fd, (type == IRQ_READ));
|
maybe_sigio_broken(fd, (type == IRQ_READ));
|
||||||
@@ -264,13 +249,14 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (irq == NULL) {
|
if (irq == NULL) {
|
||||||
printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
|
printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n",
|
||||||
|
fd);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fdi = os_get_pollfd(i);
|
fdi = os_get_pollfd(i);
|
||||||
if ((fdi != -1) && (fdi != fd)) {
|
if ((fdi != -1) && (fdi != fd)) {
|
||||||
printk("find_irq_by_fd - mismatch between active_fds and "
|
printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds "
|
||||||
"pollfds, fd %d vs %d, need %d\n", irq->fd,
|
"and pollfds, fd %d vs %d, need %d\n", irq->fd,
|
||||||
fdi, fd);
|
fdi, fd);
|
||||||
irq = NULL;
|
irq = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -372,8 +358,10 @@ int um_request_irq(unsigned int irq, int fd, int type,
|
|||||||
EXPORT_SYMBOL(um_request_irq);
|
EXPORT_SYMBOL(um_request_irq);
|
||||||
EXPORT_SYMBOL(reactivate_fd);
|
EXPORT_SYMBOL(reactivate_fd);
|
||||||
|
|
||||||
/* hw_interrupt_type must define (startup || enable) &&
|
/*
|
||||||
* (shutdown || disable) && end */
|
* hw_interrupt_type must define (startup || enable) &&
|
||||||
|
* (shutdown || disable) && end
|
||||||
|
*/
|
||||||
static void dummy(unsigned int irq)
|
static void dummy(unsigned int irq)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -422,7 +410,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
|
|||||||
|
|
||||||
err = os_pipe(fds, 1, 1);
|
err = os_pipe(fds, 1, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
|
printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n",
|
||||||
|
-err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +419,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
|
|||||||
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
|
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
|
||||||
(void *) (long) fds[0]);
|
(void *) (long) fds[0]);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init_aio_irq - : um_request_irq failed, err = %d\n",
|
printk(KERN_ERR "init_aio_irq - : um_request_irq failed, "
|
||||||
|
"err = %d\n",
|
||||||
err);
|
err);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
@@ -502,7 +492,8 @@ unsigned long to_irq_stack(unsigned long *mask_out)
|
|||||||
|
|
||||||
mask = xchg(&pending_mask, *mask_out);
|
mask = xchg(&pending_mask, *mask_out);
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
/* If any interrupts come in at this point, we want to
|
/*
|
||||||
|
* If any interrupts come in at this point, we want to
|
||||||
* make sure that their bits aren't lost by our
|
* make sure that their bits aren't lost by our
|
||||||
* putting our bit in. So, this loop accumulates bits
|
* putting our bit in. So, this loop accumulates bits
|
||||||
* until xchg returns the same value that we put in.
|
* until xchg returns the same value that we put in.
|
||||||
|
@@ -75,7 +75,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
|
|||||||
err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
|
err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == -ENOMEM)
|
if (err == -ENOMEM)
|
||||||
printk("try increasing the host's "
|
printk(KERN_ERR "try increasing the host's "
|
||||||
"/proc/sys/vm/max_map_count to <physical "
|
"/proc/sys/vm/max_map_count to <physical "
|
||||||
"memory size>/4096\n");
|
"memory size>/4096\n");
|
||||||
panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
|
panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
|
||||||
@@ -103,7 +103,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special kludge - This page will be mapped in to userspace processes
|
/*
|
||||||
|
* Special kludge - This page will be mapped in to userspace processes
|
||||||
* from physmem_fd, so it needs to be written out there.
|
* from physmem_fd, so it needs to be written out there.
|
||||||
*/
|
*/
|
||||||
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
|
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
|
||||||
@@ -202,8 +203,8 @@ int setup_iomem(void)
|
|||||||
err = os_map_memory((void *) iomem_start, region->fd, 0,
|
err = os_map_memory((void *) iomem_start, region->fd, 0,
|
||||||
region->size, 1, 1, 0);
|
region->size, 1, 1, 0);
|
||||||
if (err)
|
if (err)
|
||||||
printk("Mapping iomem region for driver '%s' failed, "
|
printk(KERN_ERR "Mapping iomem region for driver '%s' "
|
||||||
"errno = %d\n", region->driver, -err);
|
"failed, errno = %d\n", region->driver, -err);
|
||||||
else {
|
else {
|
||||||
region->virt = iomem_start;
|
region->virt = iomem_start;
|
||||||
region->phys = __pa(region->virt);
|
region->phys = __pa(region->virt);
|
||||||
|
@@ -1,51 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Copyright 2003 PathScale, Inc.
|
* Copyright 2003 PathScale, Inc.
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/kernel.h"
|
#include "linux/stddef.h"
|
||||||
#include "linux/sched.h"
|
#include "linux/err.h"
|
||||||
#include "linux/interrupt.h"
|
#include "linux/hardirq.h"
|
||||||
#include "linux/string.h"
|
|
||||||
#include "linux/mm.h"
|
#include "linux/mm.h"
|
||||||
#include "linux/slab.h"
|
#include "linux/personality.h"
|
||||||
#include "linux/utsname.h"
|
|
||||||
#include "linux/fs.h"
|
|
||||||
#include "linux/utime.h"
|
|
||||||
#include "linux/smp_lock.h"
|
|
||||||
#include "linux/module.h"
|
|
||||||
#include "linux/init.h"
|
|
||||||
#include "linux/capability.h"
|
|
||||||
#include "linux/vmalloc.h"
|
|
||||||
#include "linux/spinlock.h"
|
|
||||||
#include "linux/proc_fs.h"
|
#include "linux/proc_fs.h"
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
#include "linux/random.h"
|
#include "linux/random.h"
|
||||||
#include "linux/personality.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/unistd.h"
|
#include "linux/threads.h"
|
||||||
#include "asm/mman.h"
|
|
||||||
#include "asm/segment.h"
|
|
||||||
#include "asm/stat.h"
|
|
||||||
#include "asm/pgtable.h"
|
#include "asm/pgtable.h"
|
||||||
#include "asm/processor.h"
|
|
||||||
#include "asm/tlbflush.h"
|
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "asm/user.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
#include "kern.h"
|
#include "kern_util.h"
|
||||||
#include "signal_kern.h"
|
|
||||||
#include "init.h"
|
|
||||||
#include "irq_user.h"
|
|
||||||
#include "mem_user.h"
|
|
||||||
#include "tlb.h"
|
|
||||||
#include "frame_kern.h"
|
|
||||||
#include "sigcontext.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
|
||||||
/* This is a per-cpu array. A processor only modifies its entry and it only
|
/*
|
||||||
|
* This is a per-cpu array. A processor only modifies its entry and it only
|
||||||
* cares about its entry, so it's OK if another processor is modifying its
|
* cares about its entry, so it's OK if another processor is modifying its
|
||||||
* entry.
|
* entry.
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +32,7 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
|
|||||||
static inline int external_pid(struct task_struct *task)
|
static inline int external_pid(struct task_struct *task)
|
||||||
{
|
{
|
||||||
/* FIXME: Need to look up userspace_pid by cpu */
|
/* FIXME: Need to look up userspace_pid by cpu */
|
||||||
return(userspace_pid[0]);
|
return userspace_pid[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int pid_to_processor_id(int pid)
|
int pid_to_processor_id(int pid)
|
||||||
@@ -158,7 +136,8 @@ void *get_current(void)
|
|||||||
|
|
||||||
extern void schedule_tail(struct task_struct *prev);
|
extern void schedule_tail(struct task_struct *prev);
|
||||||
|
|
||||||
/* This is called magically, by its address being stuffed in a jmp_buf
|
/*
|
||||||
|
* This is called magically, by its address being stuffed in a jmp_buf
|
||||||
* and being longjmp-d to.
|
* and being longjmp-d to.
|
||||||
*/
|
*/
|
||||||
void new_thread_handler(void)
|
void new_thread_handler(void)
|
||||||
@@ -173,7 +152,8 @@ void new_thread_handler(void)
|
|||||||
fn = current->thread.request.u.thread.proc;
|
fn = current->thread.request.u.thread.proc;
|
||||||
arg = current->thread.request.u.thread.arg;
|
arg = current->thread.request.u.thread.arg;
|
||||||
|
|
||||||
/* The return value is 1 if the kernel thread execs a process,
|
/*
|
||||||
|
* The return value is 1 if the kernel thread execs a process,
|
||||||
* 0 if it just exits
|
* 0 if it just exits
|
||||||
*/
|
*/
|
||||||
n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf);
|
n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf);
|
||||||
@@ -194,9 +174,11 @@ void fork_handler(void)
|
|||||||
|
|
||||||
schedule_tail(current->thread.prev_sched);
|
schedule_tail(current->thread.prev_sched);
|
||||||
|
|
||||||
/* XXX: if interrupt_end() calls schedule, this call to
|
/*
|
||||||
|
* XXX: if interrupt_end() calls schedule, this call to
|
||||||
* arch_switch_to isn't needed. We could want to apply this to
|
* arch_switch_to isn't needed. We could want to apply this to
|
||||||
* improve performance. -bb */
|
* improve performance. -bb
|
||||||
|
*/
|
||||||
arch_switch_to(current->thread.prev_sched, current);
|
arch_switch_to(current->thread.prev_sched, current);
|
||||||
|
|
||||||
current->thread.prev_sched = NULL;
|
current->thread.prev_sched = NULL;
|
||||||
@@ -408,7 +390,8 @@ int get_using_sysemu(void)
|
|||||||
|
|
||||||
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
|
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
|
||||||
{
|
{
|
||||||
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
|
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size)
|
||||||
|
/* No overflow */
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
||||||
return strlen(buf);
|
return strlen(buf);
|
||||||
@@ -423,7 +406,8 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned
|
|||||||
|
|
||||||
if (tmp[0] >= '0' && tmp[0] <= '2')
|
if (tmp[0] >= '0' && tmp[0] <= '2')
|
||||||
set_using_sysemu(tmp[0] - '0');
|
set_using_sysemu(tmp[0] - '0');
|
||||||
return count; /*We use the first char, but pretend to write everything*/
|
/* We use the first char, but pretend to write everything */
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init make_proc_sysemu(void)
|
int __init make_proc_sysemu(void)
|
||||||
@@ -453,10 +437,10 @@ int singlestepping(void * t)
|
|||||||
struct task_struct *task = t ? t : current;
|
struct task_struct *task = t ? t : current;
|
||||||
|
|
||||||
if ( ! (task->ptrace & PT_DTRACE) )
|
if ( ! (task->ptrace & PT_DTRACE) )
|
||||||
return(0);
|
return 0;
|
||||||
|
|
||||||
if (task->thread.singlestep_syscall)
|
if (task->thread.singlestep_syscall)
|
||||||
return(1);
|
return 1;
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/mm.h"
|
|
||||||
#include "linux/errno.h"
|
|
||||||
#include "linux/smp_lock.h"
|
|
||||||
#include "linux/security.h"
|
|
||||||
#include "linux/ptrace.h"
|
|
||||||
#include "linux/audit.h"
|
#include "linux/audit.h"
|
||||||
#ifdef CONFIG_PROC_MM
|
#include "linux/ptrace.h"
|
||||||
#include "linux/proc_mm.h"
|
#include "linux/sched.h"
|
||||||
#endif
|
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "kern_util.h"
|
#ifdef CONFIG_PROC_MM
|
||||||
|
#include "proc_mm.h"
|
||||||
|
#endif
|
||||||
#include "skas_ptrace.h"
|
#include "skas_ptrace.h"
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
static inline void set_singlestepping(struct task_struct *child, int on)
|
static inline void set_singlestepping(struct task_struct *child, int on)
|
||||||
{
|
{
|
||||||
@@ -50,8 +42,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
unsigned long __user *p = (void __user *)(unsigned long)data;
|
unsigned long __user *p = (void __user *)(unsigned long)data;
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
/* when I and D space are separate, these will need to be fixed. */
|
/* read word at location addr. */
|
||||||
case PTRACE_PEEKTEXT: /* read word at location addr. */
|
case PTRACE_PEEKTEXT:
|
||||||
case PTRACE_PEEKDATA:
|
case PTRACE_PEEKDATA:
|
||||||
ret = generic_ptrace_peekdata(child, addr, data);
|
ret = generic_ptrace_peekdata(child, addr, data);
|
||||||
break;
|
break;
|
||||||
@@ -61,29 +53,29 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
ret = peek_user(child, addr, data);
|
ret = peek_user(child, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* when I and D space are separate, this will have to be fixed. */
|
/* write the word at location addr. */
|
||||||
case PTRACE_POKETEXT: /* write the word at location addr. */
|
case PTRACE_POKETEXT:
|
||||||
case PTRACE_POKEDATA:
|
case PTRACE_POKEDATA:
|
||||||
ret = generic_ptrace_pokedata(child, addr, data);
|
ret = generic_ptrace_pokedata(child, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
|
/* write the word at location addr in the USER area */
|
||||||
|
case PTRACE_POKEUSR:
|
||||||
ret = poke_user(child, addr, data);
|
ret = poke_user(child, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
|
/* continue and stop at next (return from) syscall */
|
||||||
case PTRACE_CONT: { /* restart after signal. */
|
case PTRACE_SYSCALL:
|
||||||
|
/* restart after signal. */
|
||||||
|
case PTRACE_CONT: {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (!valid_signal(data))
|
if (!valid_signal(data))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
set_singlestepping(child, 0);
|
set_singlestepping(child, 0);
|
||||||
if (request == PTRACE_SYSCALL) {
|
if (request == PTRACE_SYSCALL)
|
||||||
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
}
|
else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
else {
|
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
|
||||||
}
|
|
||||||
child->exit_code = data;
|
child->exit_code = data;
|
||||||
wake_up_process(child);
|
wake_up_process(child);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -180,7 +172,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_FAULTINFO: {
|
case PTRACE_FAULTINFO: {
|
||||||
/* Take the info from thread->arch->faultinfo,
|
/*
|
||||||
|
* Take the info from thread->arch->faultinfo,
|
||||||
* but transfer max. sizeof(struct ptrace_faultinfo).
|
* but transfer max. sizeof(struct ptrace_faultinfo).
|
||||||
* On i386, ptrace_faultinfo is smaller!
|
* On i386, ptrace_faultinfo is smaller!
|
||||||
*/
|
*/
|
||||||
@@ -200,7 +193,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This one is confusing, so just punt and return -EIO for
|
/*
|
||||||
|
* This one is confusing, so just punt and return -EIO for
|
||||||
* now
|
* now
|
||||||
*/
|
*/
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@@ -255,7 +249,8 @@ void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
|
|||||||
force_sig_info(SIGTRAP, &info, tsk);
|
force_sig_info(SIGTRAP, &info, tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
|
/*
|
||||||
|
* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
|
||||||
* PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
|
* PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
|
||||||
*/
|
*/
|
||||||
void syscall_trace(struct uml_pt_regs *regs, int entryexit)
|
void syscall_trace(struct uml_pt_regs *regs, int entryexit)
|
||||||
@@ -285,15 +280,18 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit)
|
|||||||
if (!(current->ptrace & PT_PTRACED))
|
if (!(current->ptrace & PT_PTRACED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
/*
|
||||||
between a syscall stop and SIGTRAP delivery */
|
* the 0x80 provides a way for the tracing parent to distinguish
|
||||||
|
* between a syscall stop and SIGTRAP delivery
|
||||||
|
*/
|
||||||
tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
|
tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
|
||||||
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
|
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
|
||||||
|
|
||||||
if (entryexit) /* force do_signal() --> is_syscall() */
|
if (entryexit) /* force do_signal() --> is_syscall() */
|
||||||
set_thread_flag(TIF_SIGPENDING);
|
set_thread_flag(TIF_SIGPENDING);
|
||||||
|
|
||||||
/* this isn't the same as continuing with a signal, but it will do
|
/*
|
||||||
|
* this isn't the same as continuing with a signal, but it will do
|
||||||
* for normal use. strace only continues with a signal if the
|
* for normal use. strace only continues with a signal if the
|
||||||
* stopping signal is not SIGTRAP. -brl
|
* stopping signal is not SIGTRAP. -brl
|
||||||
*/
|
*/
|
||||||
|
@@ -1,13 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/module.h"
|
|
||||||
#include "linux/sched.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/smp.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "kern.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
|
||||||
|
@@ -1,27 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/stddef.h"
|
|
||||||
#include "linux/sys.h"
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/wait.h"
|
|
||||||
#include "linux/kernel.h"
|
|
||||||
#include "linux/smp_lock.h"
|
|
||||||
#include "linux/module.h"
|
#include "linux/module.h"
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/tty.h"
|
|
||||||
#include "linux/binfmts.h"
|
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
|
#include "linux/sched.h"
|
||||||
|
#include "asm/siginfo.h"
|
||||||
#include "asm/signal.h"
|
#include "asm/signal.h"
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "asm/unistd.h"
|
#include "asm/unistd.h"
|
||||||
#include "asm/ucontext.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "signal_kern.h"
|
|
||||||
#include "kern.h"
|
|
||||||
#include "frame_kern.h"
|
#include "frame_kern.h"
|
||||||
|
#include "kern_util.h"
|
||||||
#include "sigcontext.h"
|
#include "sigcontext.h"
|
||||||
|
|
||||||
EXPORT_SYMBOL(block_signals);
|
EXPORT_SYMBOL(block_signals);
|
||||||
@@ -112,10 +101,12 @@ static int kern_do_signal(struct pt_regs *regs)
|
|||||||
handled_sig = 1;
|
handled_sig = 1;
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
|
if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
|
||||||
/* a signal was successfully delivered; the saved
|
/*
|
||||||
|
* a signal was successfully delivered; the saved
|
||||||
* sigmask will have been stored in the signal frame,
|
* sigmask will have been stored in the signal frame,
|
||||||
* and will be restored by sigreturn, so we can simply
|
* and will be restored by sigreturn, so we can simply
|
||||||
* clear the TIF_RESTORE_SIGMASK flag */
|
* clear the TIF_RESTORE_SIGMASK flag
|
||||||
|
*/
|
||||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
break;
|
break;
|
||||||
@@ -139,7 +130,8 @@ static int kern_do_signal(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This closes a way to execute a system call on the host. If
|
/*
|
||||||
|
* This closes a way to execute a system call on the host. If
|
||||||
* you set a breakpoint on a system call instruction and singlestep
|
* you set a breakpoint on a system call instruction and singlestep
|
||||||
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
|
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
|
||||||
* rather than PTRACE_SYSCALL it, allowing the system call to execute
|
* rather than PTRACE_SYSCALL it, allowing the system call to execute
|
||||||
@@ -150,8 +142,10 @@ static int kern_do_signal(struct pt_regs *regs)
|
|||||||
current->thread.singlestep_syscall =
|
current->thread.singlestep_syscall =
|
||||||
is_syscall(PT_REGS_IP(¤t->thread.regs));
|
is_syscall(PT_REGS_IP(¤t->thread.regs));
|
||||||
|
|
||||||
/* if there's no signal to deliver, we just put the saved sigmask
|
/*
|
||||||
* back */
|
* if there's no signal to deliver, we just put the saved sigmask
|
||||||
|
* back
|
||||||
|
*/
|
||||||
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
|
# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
# Licensed under the GPL
|
# Licensed under the GPL
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@@ -1,20 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/list.h"
|
|
||||||
#include "linux/spinlock.h"
|
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/errno.h"
|
|
||||||
#include "linux/mm.h"
|
#include "linux/mm.h"
|
||||||
#include "asm/current.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/segment.h"
|
|
||||||
#include "asm/mmu.h"
|
|
||||||
#include "asm/pgalloc.h"
|
#include "asm/pgalloc.h"
|
||||||
#include "asm/pgtable.h"
|
#include "asm/pgtable.h"
|
||||||
#include "asm/ldt.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
|
||||||
@@ -41,7 +33,8 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
|
|||||||
if (!pte)
|
if (!pte)
|
||||||
goto out_pte;
|
goto out_pte;
|
||||||
|
|
||||||
/* There's an interaction between the skas0 stub pages, stack
|
/*
|
||||||
|
* There's an interaction between the skas0 stub pages, stack
|
||||||
* randomization, and the BUG at the end of exit_mmap. exit_mmap
|
* randomization, and the BUG at the end of exit_mmap. exit_mmap
|
||||||
* checks that the number of page tables freed is the same as had
|
* checks that the number of page tables freed is the same as had
|
||||||
* been allocated. If the stack is on the last page table page,
|
* been allocated. If the stack is on the last page table page,
|
||||||
@@ -61,14 +54,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
|
|||||||
|
|
||||||
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
|
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
|
||||||
*pte = pte_mkread(*pte);
|
*pte = pte_mkread(*pte);
|
||||||
return(0);
|
return 0;
|
||||||
|
|
||||||
out_pmd:
|
out_pmd:
|
||||||
pud_free(pud);
|
pud_free(pud);
|
||||||
out_pte:
|
out_pte:
|
||||||
pmd_free(pmd);
|
pmd_free(pmd);
|
||||||
out:
|
out:
|
||||||
return(-ENOMEM);
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
||||||
@@ -83,7 +76,8 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
|||||||
if (stack == 0)
|
if (stack == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* This zeros the entry that pgd_alloc didn't, needed since
|
/*
|
||||||
|
* This zeros the entry that pgd_alloc didn't, needed since
|
||||||
* we are about to reinitialize it, and want mm.nr_ptes to
|
* we are about to reinitialize it, and want mm.nr_ptes to
|
||||||
* be accurate.
|
* be accurate.
|
||||||
*/
|
*/
|
||||||
@@ -108,8 +102,8 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
|||||||
if (proc_mm) {
|
if (proc_mm) {
|
||||||
ret = new_mm(stack);
|
ret = new_mm(stack);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk("init_new_context_skas - new_mm failed, "
|
printk(KERN_ERR "init_new_context_skas - "
|
||||||
"errno = %d\n", ret);
|
"new_mm failed, errno = %d\n", ret);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
to_mm->id.u.mm_fd = ret;
|
to_mm->id.u.mm_fd = ret;
|
||||||
@@ -123,7 +117,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
|||||||
|
|
||||||
ret = init_new_ldt(to_mm, from_mm);
|
ret = init_new_ldt(to_mm, from_mm);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk("init_new_context_skas - init_ldt"
|
printk(KERN_ERR "init_new_context_skas - init_ldt"
|
||||||
" failed, errno = %d\n", ret);
|
" failed, errno = %d\n", ret);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
@@ -1,26 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/ptrace.h"
|
|
||||||
#include "linux/proc_fs.h"
|
|
||||||
#include "linux/file.h"
|
|
||||||
#include "linux/errno.h"
|
|
||||||
#include "linux/init.h"
|
#include "linux/init.h"
|
||||||
#include "asm/uaccess.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/atomic.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
#include "skas.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "tlb.h"
|
#include "skas.h"
|
||||||
#include "kern.h"
|
|
||||||
#include "registers.h"
|
|
||||||
|
|
||||||
extern void schedule_tail(struct task_struct *prev);
|
|
||||||
|
|
||||||
int new_mm(unsigned long stack)
|
int new_mm(unsigned long stack)
|
||||||
{
|
{
|
||||||
|
@@ -1,17 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sys.h"
|
#include "linux/kernel.h"
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
#include "asm/errno.h"
|
|
||||||
#include "asm/unistd.h"
|
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/current.h"
|
|
||||||
#include "sysdep/syscalls.h"
|
|
||||||
#include "kern_util.h"
|
#include "kern_util.h"
|
||||||
#include "syscall.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
#include "sysdep/syscalls.h"
|
||||||
|
|
||||||
void handle_syscall(struct uml_pt_regs *r)
|
void handle_syscall(struct uml_pt_regs *r)
|
||||||
{
|
{
|
||||||
@@ -24,7 +20,8 @@ void handle_syscall(struct uml_pt_regs *r)
|
|||||||
current->thread.nsyscalls++;
|
current->thread.nsyscalls++;
|
||||||
nsyscalls++;
|
nsyscalls++;
|
||||||
|
|
||||||
/* This should go in the declaration of syscall, but when I do that,
|
/*
|
||||||
|
* This should go in the declaration of syscall, but when I do that,
|
||||||
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
|
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
|
||||||
* children at all, sometimes hanging when bash doesn't see the first
|
* children at all, sometimes hanging when bash doesn't see the first
|
||||||
* ls exit.
|
* ls exit.
|
||||||
|
@@ -1,25 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/file.h"
|
#include "linux/file.h"
|
||||||
#include "linux/smp_lock.h"
|
|
||||||
#include "linux/mm.h"
|
|
||||||
#include "linux/fs.h"
|
#include "linux/fs.h"
|
||||||
|
#include "linux/mm.h"
|
||||||
|
#include "linux/sched.h"
|
||||||
#include "linux/utsname.h"
|
#include "linux/utsname.h"
|
||||||
#include "linux/msg.h"
|
#include "asm/current.h"
|
||||||
#include "linux/shm.h"
|
|
||||||
#include "linux/sys.h"
|
|
||||||
#include "linux/syscalls.h"
|
|
||||||
#include "linux/unistd.h"
|
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/utime.h"
|
|
||||||
#include "asm/mman.h"
|
#include "asm/mman.h"
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "kern_util.h"
|
#include "asm/unistd.h"
|
||||||
#include "sysdep/syscalls.h"
|
|
||||||
|
|
||||||
/* Unlocked, I don't care if this is a bit off */
|
/* Unlocked, I don't care if this is a bit off */
|
||||||
int nsyscalls = 0;
|
int nsyscalls = 0;
|
||||||
@@ -32,7 +24,7 @@ long sys_fork(void)
|
|||||||
ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs),
|
ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs),
|
||||||
¤t->thread.regs, 0, NULL, NULL);
|
¤t->thread.regs, 0, NULL, NULL);
|
||||||
current->thread.forking = 0;
|
current->thread.forking = 0;
|
||||||
return(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_vfork(void)
|
long sys_vfork(void)
|
||||||
@@ -44,7 +36,7 @@ long sys_vfork(void)
|
|||||||
UPT_SP(¤t->thread.regs.regs),
|
UPT_SP(¤t->thread.regs.regs),
|
||||||
¤t->thread.regs, 0, NULL, NULL);
|
¤t->thread.regs, 0, NULL, NULL);
|
||||||
current->thread.forking = 0;
|
current->thread.forking = 0;
|
||||||
return(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* common code for old and new mmaps */
|
/* common code for old and new mmaps */
|
||||||
|
@@ -1,28 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/kernel.h"
|
|
||||||
#include "linux/module.h"
|
|
||||||
#include "linux/unistd.h"
|
|
||||||
#include "linux/stddef.h"
|
|
||||||
#include "linux/spinlock.h"
|
|
||||||
#include "linux/time.h"
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/interrupt.h"
|
#include "linux/interrupt.h"
|
||||||
#include "linux/init.h"
|
#include "linux/jiffies.h"
|
||||||
#include "linux/delay.h"
|
#include "linux/threads.h"
|
||||||
#include "linux/hrtimer.h"
|
|
||||||
#include "asm/irq.h"
|
#include "asm/irq.h"
|
||||||
#include "asm/param.h"
|
#include "asm/param.h"
|
||||||
#include "asm/current.h"
|
|
||||||
#include "kern_util.h"
|
#include "kern_util.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
int hz(void)
|
int hz(void)
|
||||||
{
|
{
|
||||||
return(HZ);
|
return HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -144,7 +135,8 @@ void do_gettimeofday(struct timeval *tv)
|
|||||||
xtime.tv_nsec;
|
xtime.tv_nsec;
|
||||||
#endif
|
#endif
|
||||||
tv->tv_sec = nsecs / NSEC_PER_SEC;
|
tv->tv_sec = nsecs / NSEC_PER_SEC;
|
||||||
/* Careful about calculations here - this was originally done as
|
/*
|
||||||
|
* Careful about calculations here - this was originally done as
|
||||||
* (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
|
* (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
|
||||||
* which gave bogus (> 1000000) values. Dunno why, suspect gcc
|
* which gave bogus (> 1000000) values. Dunno why, suspect gcc
|
||||||
* (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
|
* (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
|
||||||
|
@@ -1,19 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/mm.h"
|
#include "linux/mm.h"
|
||||||
#include "asm/page.h"
|
|
||||||
#include "asm/pgalloc.h"
|
|
||||||
#include "asm/pgtable.h"
|
#include "asm/pgtable.h"
|
||||||
#include "asm/tlbflush.h"
|
#include "asm/tlbflush.h"
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
#include "tlb.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "mem_user.h"
|
#include "mem_user.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
|
||||||
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
||||||
unsigned int prot, struct host_vm_op *ops, int *index,
|
unsigned int prot, struct host_vm_op *ops, int *index,
|
||||||
@@ -251,7 +248,8 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
|||||||
|
|
||||||
/* This is not an else because ret is modified above */
|
/* This is not an else because ret is modified above */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("fix_range_common: failed, killing current process\n");
|
printk(KERN_ERR "fix_range_common: failed, killing current "
|
||||||
|
"process\n");
|
||||||
force_sig(SIGKILL, current);
|
force_sig(SIGKILL, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +336,7 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
|
|||||||
}
|
}
|
||||||
addr += PAGE_SIZE;
|
addr += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
return(updated);
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
|
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
|
||||||
@@ -402,28 +400,28 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
kill:
|
kill:
|
||||||
printk("Failed to flush page for address 0x%lx\n", address);
|
printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
|
||||||
force_sig(SIGKILL, current);
|
force_sig(SIGKILL, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
|
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
|
||||||
{
|
{
|
||||||
return(pgd_offset(mm, address));
|
return pgd_offset(mm, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
|
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
|
||||||
{
|
{
|
||||||
return(pud_offset(pgd, address));
|
return pud_offset(pgd, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
|
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
|
||||||
{
|
{
|
||||||
return(pmd_offset(pud, address));
|
return pmd_offset(pud, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
|
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
|
||||||
{
|
{
|
||||||
return(pte_offset_kernel(pmd, address));
|
return pte_offset_kernel(pmd, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
|
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
|
||||||
@@ -432,7 +430,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
|
|||||||
pud_t *pud = pud_offset(pgd, addr);
|
pud_t *pud = pud_offset(pgd, addr);
|
||||||
pmd_t *pmd = pmd_offset(pud, addr);
|
pmd_t *pmd = pmd_offset(pud, addr);
|
||||||
|
|
||||||
return(pte_offset_map(pmd, addr));
|
return pte_offset_map(pmd, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_tlb_all(void)
|
void flush_tlb_all(void)
|
||||||
@@ -480,7 +478,8 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
|
|||||||
finished, flush);
|
finished, flush);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("Unknown op type %d in do_ops\n", op->type);
|
printk(KERN_ERR "Unknown op type %d in do_ops\n",
|
||||||
|
op->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,7 +508,8 @@ void flush_tlb_mm(struct mm_struct *mm)
|
|||||||
{
|
{
|
||||||
unsigned long end;
|
unsigned long end;
|
||||||
|
|
||||||
/* Don't bother flushing if this address space is about to be
|
/*
|
||||||
|
* Don't bother flushing if this address space is about to be
|
||||||
* destroyed.
|
* destroyed.
|
||||||
*/
|
*/
|
||||||
if (atomic_read(&mm->mm_users) == 0)
|
if (atomic_read(&mm->mm_users) == 0)
|
||||||
|
@@ -1,39 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/kernel.h"
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/notifier.h"
|
|
||||||
#include "linux/mm.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "linux/tty.h"
|
|
||||||
#include "linux/init.h"
|
|
||||||
#include "linux/bootmem.h"
|
|
||||||
#include "linux/spinlock.h"
|
|
||||||
#include "linux/utsname.h"
|
|
||||||
#include "linux/sysrq.h"
|
|
||||||
#include "linux/seq_file.h"
|
|
||||||
#include "linux/delay.h"
|
#include "linux/delay.h"
|
||||||
|
#include "linux/mm.h"
|
||||||
#include "linux/module.h"
|
#include "linux/module.h"
|
||||||
|
#include "linux/seq_file.h"
|
||||||
|
#include "linux/string.h"
|
||||||
#include "linux/utsname.h"
|
#include "linux/utsname.h"
|
||||||
#include "asm/page.h"
|
|
||||||
#include "asm/pgtable.h"
|
#include "asm/pgtable.h"
|
||||||
#include "asm/ptrace.h"
|
#include "asm/processor.h"
|
||||||
#include "asm/elf.h"
|
|
||||||
#include "asm/user.h"
|
|
||||||
#include "asm/setup.h"
|
#include "asm/setup.h"
|
||||||
#include "ubd_user.h"
|
|
||||||
#include "asm/current.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "as-layout.h"
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
#include "as-layout.h"
|
||||||
|
#include "init.h"
|
||||||
#include "kern.h"
|
#include "kern.h"
|
||||||
#include "mem_user.h"
|
#include "mem_user.h"
|
||||||
#include "mem.h"
|
|
||||||
#include "initrd.h"
|
|
||||||
#include "init.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
|
||||||
@@ -223,9 +206,8 @@ static int __init uml_checksetup(char *line, int *add)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = strlen(p->str);
|
n = strlen(p->str);
|
||||||
if(!strncmp(line, p->str, n)){
|
if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
|
||||||
if (p->setup_func(line + n, add)) return 1;
|
return 1;
|
||||||
}
|
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -273,7 +255,8 @@ int __init linux_main(int argc, char **argv)
|
|||||||
char * mode;
|
char * mode;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if((i == 1) && (argv[i][0] == ' ')) continue;
|
if ((i == 1) && (argv[i][0] == ' '))
|
||||||
|
continue;
|
||||||
add = 1;
|
add = 1;
|
||||||
uml_checksetup(argv[i], &add);
|
uml_checksetup(argv[i], &add);
|
||||||
if (add)
|
if (add)
|
||||||
@@ -282,6 +265,7 @@ int __init linux_main(int argc, char **argv)
|
|||||||
if (have_root == 0)
|
if (have_root == 0)
|
||||||
add_arg(DEFAULT_COMMAND_LINE);
|
add_arg(DEFAULT_COMMAND_LINE);
|
||||||
|
|
||||||
|
/* OS sanity checks that need to happen before the kernel runs */
|
||||||
os_early_checks();
|
os_early_checks();
|
||||||
|
|
||||||
can_do_skas();
|
can_do_skas();
|
||||||
@@ -302,9 +286,11 @@ int __init linux_main(int argc, char **argv)
|
|||||||
|
|
||||||
brk_start = (unsigned long) sbrk(0);
|
brk_start = (unsigned long) sbrk(0);
|
||||||
|
|
||||||
/* Increase physical memory size for exec-shield users
|
/*
|
||||||
so they actually get what they asked for. This should
|
* Increase physical memory size for exec-shield users
|
||||||
add zero for non-exec shield users */
|
* so they actually get what they asked for. This should
|
||||||
|
* add zero for non-exec shield users
|
||||||
|
*/
|
||||||
|
|
||||||
diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
|
diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
|
||||||
if (diff > 1024 * 1024) {
|
if (diff > 1024 * 1024) {
|
||||||
@@ -324,7 +310,8 @@ int __init linux_main(int argc, char **argv)
|
|||||||
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
|
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||||
max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
|
max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
|
||||||
|
|
||||||
/* Zones have to begin on a 1 << MAX_ORDER page boundary,
|
/*
|
||||||
|
* Zones have to begin on a 1 << MAX_ORDER page boundary,
|
||||||
* so this makes sure that's true for highmem
|
* so this makes sure that's true for highmem
|
||||||
*/
|
*/
|
||||||
max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
|
max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
|
||||||
@@ -354,7 +341,8 @@ int __init linux_main(int argc, char **argv)
|
|||||||
|
|
||||||
virtmem_size = physmem_size;
|
virtmem_size = physmem_size;
|
||||||
avail = get_kmem_end() - start_vm;
|
avail = get_kmem_end() - start_vm;
|
||||||
if(physmem_size > avail) virtmem_size = avail;
|
if (physmem_size > avail)
|
||||||
|
virtmem_size = avail;
|
||||||
end_vm = start_vm + virtmem_size;
|
end_vm = start_vm + virtmem_size;
|
||||||
|
|
||||||
if (virtmem_size < physmem_size)
|
if (virtmem_size < physmem_size)
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sched.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sched.h>
|
#include <sys/time.h>
|
||||||
#include <sys/syscall.h>
|
#include <asm/unistd.h>
|
||||||
#include "os.h"
|
|
||||||
#include "aio.h"
|
#include "aio.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "user.h"
|
|
||||||
#include "kern_constants.h"
|
#include "kern_constants.h"
|
||||||
|
#include "os.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
struct aio_thread_req {
|
struct aio_thread_req {
|
||||||
enum aio_type type;
|
enum aio_type type;
|
||||||
@@ -27,7 +27,8 @@ struct aio_thread_req {
|
|||||||
#if defined(HAVE_AIO_ABI)
|
#if defined(HAVE_AIO_ABI)
|
||||||
#include <linux/aio_abi.h>
|
#include <linux/aio_abi.h>
|
||||||
|
|
||||||
/* If we have the headers, we are going to build with AIO enabled.
|
/*
|
||||||
|
* If we have the headers, we are going to build with AIO enabled.
|
||||||
* If we don't have aio in libc, we define the necessary stubs here.
|
* If we don't have aio in libc, we define the necessary stubs here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -51,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The AIO_MMAP cases force the mmapped page into memory here
|
/*
|
||||||
|
* The AIO_MMAP cases force the mmapped page into memory here
|
||||||
* rather than in whatever place first touches the data. I used
|
* rather than in whatever place first touches the data. I used
|
||||||
* to do this by touching the page, but that's delicate because
|
* to do this by touching the page, but that's delicate because
|
||||||
* gcc is prone to optimizing that away. So, what's done here
|
* gcc is prone to optimizing that away. So, what's done here
|
||||||
@@ -110,7 +112,7 @@ static int aio_thread(void *arg)
|
|||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
printk("aio_thread - io_getevents failed, "
|
printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
|
||||||
"errno = %d\n", errno);
|
"errno = %d\n", errno);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -120,8 +122,8 @@ static int aio_thread(void *arg)
|
|||||||
reply_fd = ((struct aio_context *) reply.data)->reply_fd;
|
reply_fd = ((struct aio_context *) reply.data)->reply_fd;
|
||||||
err = write(reply_fd, &reply, sizeof(reply));
|
err = write(reply_fd, &reply, sizeof(reply));
|
||||||
if (err != sizeof(reply))
|
if (err != sizeof(reply))
|
||||||
printk("aio_thread - write failed, fd = %d, "
|
printk(UM_KERN_ERR "aio_thread - write failed, "
|
||||||
"err = %d\n", reply_fd, errno);
|
"fd = %d, err = %d\n", reply_fd, errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -150,7 +152,8 @@ static int do_not_aio(struct aio_thread_req *req)
|
|||||||
n = read(req->io_fd, &c, sizeof(c));
|
n = read(req->io_fd, &c, sizeof(c));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("do_not_aio - bad request type : %d\n", req->type);
|
printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
|
||||||
|
req->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,12 +179,14 @@ static int not_aio_thread(void *arg)
|
|||||||
err = read(aio_req_fd_r, &req, sizeof(req));
|
err = read(aio_req_fd_r, &req, sizeof(req));
|
||||||
if (err != sizeof(req)) {
|
if (err != sizeof(req)) {
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
printk("not_aio_thread - read failed, "
|
printk(UM_KERN_ERR "not_aio_thread - "
|
||||||
"fd = %d, err = %d\n", aio_req_fd_r,
|
"read failed, fd = %d, err = %d\n",
|
||||||
|
aio_req_fd_r,
|
||||||
errno);
|
errno);
|
||||||
else {
|
else {
|
||||||
printk("not_aio_thread - short read, fd = %d, "
|
printk(UM_KERN_ERR "not_aio_thread - short "
|
||||||
"length = %d\n", aio_req_fd_r, err);
|
"read, fd = %d, length = %d\n",
|
||||||
|
aio_req_fd_r, err);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -190,8 +195,8 @@ static int not_aio_thread(void *arg)
|
|||||||
.err = err });
|
.err = err });
|
||||||
err = write(req.aio->reply_fd, &reply, sizeof(reply));
|
err = write(req.aio->reply_fd, &reply, sizeof(reply));
|
||||||
if (err != sizeof(reply))
|
if (err != sizeof(reply))
|
||||||
printk("not_aio_thread - write failed, fd = %d, "
|
printk(UM_KERN_ERR "not_aio_thread - write failed, "
|
||||||
"err = %d\n", req.aio->reply_fd, errno);
|
"fd = %d, err = %d\n", req.aio->reply_fd, errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -227,10 +232,11 @@ out_close_pipe:
|
|||||||
aio_req_fd_r = -1;
|
aio_req_fd_r = -1;
|
||||||
out:
|
out:
|
||||||
#ifndef HAVE_AIO_ABI
|
#ifndef HAVE_AIO_ABI
|
||||||
printk("/usr/include/linux/aio_abi.h not present during build\n");
|
printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
|
||||||
|
"build\n");
|
||||||
#endif
|
#endif
|
||||||
printk("2.6 host AIO support not used - falling back to I/O "
|
printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
|
||||||
"thread\n");
|
"I/O thread\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,8 +248,8 @@ static int init_aio_26(void)
|
|||||||
|
|
||||||
if (io_setup(256, &ctx)) {
|
if (io_setup(256, &ctx)) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
printk("aio_thread failed to initialize context, err = %d\n",
|
printk(UM_KERN_ERR "aio_thread failed to initialize context, "
|
||||||
errno);
|
"err = %d\n", errno);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +260,7 @@ static int init_aio_26(void)
|
|||||||
|
|
||||||
aio_pid = err;
|
aio_pid = err;
|
||||||
|
|
||||||
printk("Using 2.6 host AIO\n");
|
printk(UM_KERN_INFO "Using 2.6 host AIO\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +277,7 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
|
|||||||
err = write(aio->reply_fd, &reply, sizeof(reply));
|
err = write(aio->reply_fd, &reply, sizeof(reply));
|
||||||
if (err != sizeof(reply)) {
|
if (err != sizeof(reply)) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
printk("submit_aio_26 - write failed, "
|
printk(UM_KERN_ERR "submit_aio_26 - write failed, "
|
||||||
"fd = %d, err = %d\n", aio->reply_fd, -err);
|
"fd = %d, err = %d\n", aio->reply_fd, -err);
|
||||||
}
|
}
|
||||||
else err = 0;
|
else err = 0;
|
||||||
@@ -322,8 +328,8 @@ static int init_aio(void)
|
|||||||
if (!aio_24) {
|
if (!aio_24) {
|
||||||
err = init_aio_26();
|
err = init_aio_26();
|
||||||
if (err && (errno == ENOSYS)) {
|
if (err && (errno == ENOSYS)) {
|
||||||
printk("2.6 AIO not supported on the host - "
|
printk(UM_KERN_INFO "2.6 AIO not supported on the "
|
||||||
"reverting to 2.4 AIO\n");
|
"host - reverting to 2.4 AIO\n");
|
||||||
aio_24 = 1;
|
aio_24 = 1;
|
||||||
}
|
}
|
||||||
else return err;
|
else return err;
|
||||||
@@ -335,7 +341,8 @@ static int init_aio(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
|
/*
|
||||||
|
* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
|
||||||
* needs to be called when the kernel is running because it calls run_helper,
|
* needs to be called when the kernel is running because it calls run_helper,
|
||||||
* which needs get_free_page. exit_aio is a __uml_exitcall because the generic
|
* which needs get_free_page. exit_aio is a __uml_exitcall because the generic
|
||||||
* kernel does not run __exitcalls on shutdown, and can't because many of them
|
* kernel does not run __exitcalls on shutdown, and can't because many of them
|
||||||
@@ -380,7 +387,6 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
|
|||||||
aio->reply_fd = reply_fd;
|
aio->reply_fd = reply_fd;
|
||||||
if (aio_24)
|
if (aio_24)
|
||||||
return submit_aio_24(type, io_fd, buf, len, offset, aio);
|
return submit_aio_24(type, io_fd, buf, len, offset, aio);
|
||||||
else {
|
else
|
||||||
return submit_aio_26(type, io_fd, buf, len, offset, aio);
|
return submit_aio_26(type, io_fd, buf, len, offset, aio);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@@ -267,9 +267,9 @@ void os_close_file(int fd)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int os_seek_file(int fd, __u64 offset)
|
int os_seek_file(int fd, unsigned long long offset)
|
||||||
{
|
{
|
||||||
__u64 actual;
|
unsigned long long actual;
|
||||||
|
|
||||||
actual = lseek64(fd, offset, SEEK_SET);
|
actual = lseek64(fd, offset, SEEK_SET);
|
||||||
if(actual != offset)
|
if(actual != offset)
|
||||||
|
@@ -1,27 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
#include "mem_user.h"
|
|
||||||
#include "irq_user.h"
|
|
||||||
#include "user.h"
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "uml-config.h"
|
#include "kern_constants.h"
|
||||||
|
#include "kern_util.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "um_malloc.h"
|
#include "um_malloc.h"
|
||||||
#include "kern_constants.h"
|
|
||||||
|
|
||||||
#define PGD_BOUND (4 * 1024 * 1024)
|
#define PGD_BOUND (4 * 1024 * 1024)
|
||||||
#define STACKSIZE (8 * 1024 * 1024)
|
#define STACKSIZE (8 * 1024 * 1024)
|
||||||
@@ -68,7 +62,8 @@ static void install_fatal_handler(int sig)
|
|||||||
/* All signals are enabled in this handler ... */
|
/* All signals are enabled in this handler ... */
|
||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
/* ... including the signal being handled, plus we want the
|
/*
|
||||||
|
* ... including the signal being handled, plus we want the
|
||||||
* handler reset to the default behavior, so that if an exit
|
* handler reset to the default behavior, so that if an exit
|
||||||
* handler is hanging for some reason, the UML will just die
|
* handler is hanging for some reason, the UML will just die
|
||||||
* after this signal is sent a second time.
|
* after this signal is sent a second time.
|
||||||
@@ -92,7 +87,8 @@ static void setup_env_path(void)
|
|||||||
int path_len = 0;
|
int path_len = 0;
|
||||||
|
|
||||||
old_path = getenv("PATH");
|
old_path = getenv("PATH");
|
||||||
/* if no PATH variable is set or it has an empty value
|
/*
|
||||||
|
* if no PATH variable is set or it has an empty value
|
||||||
* just use the default + /usr/lib/uml
|
* just use the default + /usr/lib/uml
|
||||||
*/
|
*/
|
||||||
if (!old_path || (path_len = strlen(old_path)) == 0) {
|
if (!old_path || (path_len = strlen(old_path)) == 0) {
|
||||||
@@ -138,7 +134,8 @@ int __init main(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
new_argv[argc] = NULL;
|
new_argv[argc] = NULL;
|
||||||
|
|
||||||
/* Allow these signals to bring down a UML if all other
|
/*
|
||||||
|
* Allow these signals to bring down a UML if all other
|
||||||
* methods of control fail.
|
* methods of control fail.
|
||||||
*/
|
*/
|
||||||
install_fatal_handler(SIGINT);
|
install_fatal_handler(SIGINT);
|
||||||
@@ -150,13 +147,15 @@ int __init main(int argc, char **argv, char **envp)
|
|||||||
do_uml_initcalls();
|
do_uml_initcalls();
|
||||||
ret = linux_main(argc, argv);
|
ret = linux_main(argc, argv);
|
||||||
|
|
||||||
/* Disable SIGPROF - I have no idea why libc doesn't do this or turn
|
/*
|
||||||
|
* Disable SIGPROF - I have no idea why libc doesn't do this or turn
|
||||||
* off the profiling time, but UML dies with a SIGPROF just before
|
* off the profiling time, but UML dies with a SIGPROF just before
|
||||||
* exiting when profiling is active.
|
* exiting when profiling is active.
|
||||||
*/
|
*/
|
||||||
change_sig(SIGPROF, 0);
|
change_sig(SIGPROF, 0);
|
||||||
|
|
||||||
/* This signal stuff used to be in the reboot case. However,
|
/*
|
||||||
|
* This signal stuff used to be in the reboot case. However,
|
||||||
* sometimes a SIGVTALRM can come in when we're halting (reproducably
|
* sometimes a SIGVTALRM can come in when we're halting (reproducably
|
||||||
* when writing out gcov information, presumably because that takes
|
* when writing out gcov information, presumably because that takes
|
||||||
* some time) and cause a segfault.
|
* some time) and cause a segfault.
|
||||||
@@ -170,7 +169,8 @@ int __init main(int argc, char **argv, char **envp)
|
|||||||
if (err)
|
if (err)
|
||||||
printf("deactivate_all_fds failed, errno = %d\n", -err);
|
printf("deactivate_all_fds failed, errno = %d\n", -err);
|
||||||
|
|
||||||
/* Let any pending signals fire now. This ensures
|
/*
|
||||||
|
* Let any pending signals fire now. This ensures
|
||||||
* that they won't be delivered after the exec, when
|
* that they won't be delivered after the exec, when
|
||||||
* they are definitely not expected.
|
* they are definitely not expected.
|
||||||
*/
|
*/
|
||||||
@@ -200,7 +200,8 @@ void *__wrap_malloc(int size)
|
|||||||
ret = kmalloc(size, UM_GFP_KERNEL);
|
ret = kmalloc(size, UM_GFP_KERNEL);
|
||||||
else ret = vmalloc(size);
|
else ret = vmalloc(size);
|
||||||
|
|
||||||
/* glibc people insist that if malloc fails, errno should be
|
/*
|
||||||
|
* glibc people insist that if malloc fails, errno should be
|
||||||
* set by malloc as well. So we do.
|
* set by malloc as well. So we do.
|
||||||
*/
|
*/
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
@@ -227,7 +228,8 @@ void __wrap_free(void *ptr)
|
|||||||
{
|
{
|
||||||
unsigned long addr = (unsigned long) ptr;
|
unsigned long addr = (unsigned long) ptr;
|
||||||
|
|
||||||
/* We need to know how the allocation happened, so it can be correctly
|
/*
|
||||||
|
* We need to know how the allocation happened, so it can be correctly
|
||||||
* freed. This is done by seeing what region of memory the pointer is
|
* freed. This is done by seeing what region of memory the pointer is
|
||||||
* in -
|
* in -
|
||||||
* physical memory - kmalloc/kfree
|
* physical memory - kmalloc/kfree
|
||||||
|
@@ -1,27 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/mman.h>
|
#include <asm/unistd.h>
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include "ptrace_user.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "user.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "irq_user.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "longjmp.h"
|
|
||||||
#include "skas_ptrace.h"
|
|
||||||
#include "kern_constants.h"
|
|
||||||
#include "uml-config.h"
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "kern_constants.h"
|
||||||
|
#include "longjmp.h"
|
||||||
|
#include "os.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "skas_ptrace.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
#define ARBITRARY_ADDR -1
|
#define ARBITRARY_ADDR -1
|
||||||
#define FAILURE_PID -1
|
#define FAILURE_PID -1
|
||||||
@@ -38,14 +34,14 @@ unsigned long os_process_pc(int pid)
|
|||||||
sprintf(proc_stat, "/proc/%d/stat", pid);
|
sprintf(proc_stat, "/proc/%d/stat", pid);
|
||||||
fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
|
fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("os_process_pc - couldn't open '%s', err = %d\n",
|
printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
|
||||||
proc_stat, -fd);
|
"err = %d\n", proc_stat, -fd);
|
||||||
return ARBITRARY_ADDR;
|
return ARBITRARY_ADDR;
|
||||||
}
|
}
|
||||||
CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
|
CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk("os_process_pc - couldn't read '%s', err = %d\n",
|
printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
|
||||||
proc_stat, errno);
|
"err = %d\n", proc_stat, errno);
|
||||||
os_close_file(fd);
|
os_close_file(fd);
|
||||||
return ARBITRARY_ADDR;
|
return ARBITRARY_ADDR;
|
||||||
}
|
}
|
||||||
@@ -54,7 +50,8 @@ unsigned long os_process_pc(int pid)
|
|||||||
if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
|
if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
|
||||||
"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
|
"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
|
||||||
"%*d %*d %*d %*d %*d %lu", &pc) != 1) {
|
"%*d %*d %*d %*d %*d %lu", &pc) != 1) {
|
||||||
printk("os_process_pc - couldn't find pc in '%s'\n", buf);
|
printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
|
||||||
|
buf);
|
||||||
}
|
}
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
@@ -71,7 +68,7 @@ int os_process_parent(int pid)
|
|||||||
snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
|
snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
|
||||||
fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
|
fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("Couldn't open '%s', err = %d\n", stat, -fd);
|
printk(UM_KERN_ERR "Couldn't open '%s', err = %d\n", stat, -fd);
|
||||||
return FAILURE_PID;
|
return FAILURE_PID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +76,15 @@ int os_process_parent(int pid)
|
|||||||
os_close_file(fd);
|
os_close_file(fd);
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
printk("Couldn't read '%s', err = %d\n", stat, errno);
|
printk(UM_KERN_ERR "Couldn't read '%s', err = %d\n", stat,
|
||||||
|
errno);
|
||||||
return FAILURE_PID;
|
return FAILURE_PID;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = FAILURE_PID;
|
parent = FAILURE_PID;
|
||||||
n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
|
n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
|
||||||
if (n != 1)
|
if (n != 1)
|
||||||
printk("Failed to scan '%s'\n", data);
|
printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
@@ -101,7 +99,6 @@ void os_kill_process(int pid, int reap_child)
|
|||||||
kill(pid, SIGKILL);
|
kill(pid, SIGKILL);
|
||||||
if (reap_child)
|
if (reap_child)
|
||||||
CATCH_EINTR(waitpid(pid, NULL, 0));
|
CATCH_EINTR(waitpid(pid, NULL, 0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is here uniquely to have access to the userspace errno, i.e. the one
|
/* This is here uniquely to have access to the userspace errno, i.e. the one
|
||||||
@@ -170,6 +167,7 @@ int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
|
|||||||
|
|
||||||
if (mprotect(addr, len, prot) < 0)
|
if (mprotect(addr, len, prot) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,22 +200,24 @@ int __init can_drop_memory(void)
|
|||||||
void *addr;
|
void *addr;
|
||||||
int fd, ok = 0;
|
int fd, ok = 0;
|
||||||
|
|
||||||
printk("Checking host MADV_REMOVE support...");
|
printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
|
||||||
fd = create_mem_file(UM_KERN_PAGE_SIZE);
|
fd = create_mem_file(UM_KERN_PAGE_SIZE);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("Creating test memory file failed, err = %d\n", -fd);
|
printk(UM_KERN_ERR "Creating test memory file failed, "
|
||||||
|
"err = %d\n", -fd);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, fd, 0);
|
MAP_SHARED, fd, 0);
|
||||||
if (addr == MAP_FAILED) {
|
if (addr == MAP_FAILED) {
|
||||||
printk("Mapping test memory file failed, err = %d\n", -errno);
|
printk(UM_KERN_ERR "Mapping test memory file failed, "
|
||||||
|
"err = %d\n", -errno);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
|
if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
|
||||||
printk("MADV_REMOVE failed, err = %d\n", -errno);
|
printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
|
||||||
goto out_unmap;
|
goto out_unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2004 PathScale, Inc
|
* Copyright (C) 2004 PathScale, Inc
|
||||||
|
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include "user.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
/* This is set once at boot time and not changed thereafter */
|
/* This is set once at boot time and not changed thereafter */
|
||||||
|
|
||||||
|
@@ -1,24 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2004 PathScale, Inc
|
* Copyright (C) 2004 PathScale, Inc
|
||||||
|
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <errno.h>
|
||||||
#include <sys/mman.h>
|
#include <signal.h>
|
||||||
#include "user.h"
|
#include <strings.h>
|
||||||
#include "signal_kern.h"
|
|
||||||
#include "sysdep/sigcontext.h"
|
|
||||||
#include "sysdep/barrier.h"
|
|
||||||
#include "sigcontext.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "sysdep/barrier.h"
|
||||||
|
#include "sysdep/sigcontext.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
|
/*
|
||||||
|
* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
|
||||||
* together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
|
* together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
|
||||||
* be able to profile all of UML, not just the non-critical sections. If
|
* be able to profile all of UML, not just the non-critical sections. If
|
||||||
* profiling is not thread-safe, then that is not my problem. We can disable
|
* profiling is not thread-safe, then that is not my problem. We can disable
|
||||||
@@ -33,7 +30,8 @@
|
|||||||
#define SIGALRM_BIT 2
|
#define SIGALRM_BIT 2
|
||||||
#define SIGALRM_MASK (1 << SIGALRM_BIT)
|
#define SIGALRM_MASK (1 << SIGALRM_BIT)
|
||||||
|
|
||||||
/* These are used by both the signal handlers and
|
/*
|
||||||
|
* These are used by both the signal handlers and
|
||||||
* block/unblock_signals. I don't want modifications cached in a
|
* block/unblock_signals. I don't want modifications cached in a
|
||||||
* register - they must go straight to memory.
|
* register - they must go straight to memory.
|
||||||
*/
|
*/
|
||||||
@@ -145,7 +143,8 @@ void handle_signal(int sig, struct sigcontext *sc)
|
|||||||
(*handlers[sig])(sig, sc);
|
(*handlers[sig])(sig, sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Again, pending comes back with a mask of signals
|
/*
|
||||||
|
* Again, pending comes back with a mask of signals
|
||||||
* that arrived while tearing down the stack. If this
|
* that arrived while tearing down the stack. If this
|
||||||
* is non-zero, we just go back, set up the stack
|
* is non-zero, we just go back, set up the stack
|
||||||
* again, and handle the new interrupts.
|
* again, and handle the new interrupts.
|
||||||
@@ -192,13 +191,14 @@ int change_sig(int signal, int on)
|
|||||||
sigemptyset(&sigset);
|
sigemptyset(&sigset);
|
||||||
sigaddset(&sigset, signal);
|
sigaddset(&sigset, signal);
|
||||||
sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
|
sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
|
||||||
return(!sigismember(&old, signal));
|
return !sigismember(&old, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_signals(void)
|
void block_signals(void)
|
||||||
{
|
{
|
||||||
signals_enabled = 0;
|
signals_enabled = 0;
|
||||||
/* This must return with signals disabled, so this barrier
|
/*
|
||||||
|
* This must return with signals disabled, so this barrier
|
||||||
* ensures that writes are flushed out before the return.
|
* ensures that writes are flushed out before the return.
|
||||||
* This might matter if gcc figures out how to inline this and
|
* This might matter if gcc figures out how to inline this and
|
||||||
* decides to shuffle this code into the caller.
|
* decides to shuffle this code into the caller.
|
||||||
@@ -213,24 +213,28 @@ void unblock_signals(void)
|
|||||||
if (signals_enabled == 1)
|
if (signals_enabled == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We loop because the IRQ handler returns with interrupts off. So,
|
/*
|
||||||
|
* We loop because the IRQ handler returns with interrupts off. So,
|
||||||
* interrupts may have arrived and we need to re-enable them and
|
* interrupts may have arrived and we need to re-enable them and
|
||||||
* recheck pending.
|
* recheck pending.
|
||||||
*/
|
*/
|
||||||
while(1) {
|
while(1) {
|
||||||
/* Save and reset save_pending after enabling signals. This
|
/*
|
||||||
|
* Save and reset save_pending after enabling signals. This
|
||||||
* way, pending won't be changed while we're reading it.
|
* way, pending won't be changed while we're reading it.
|
||||||
*/
|
*/
|
||||||
signals_enabled = 1;
|
signals_enabled = 1;
|
||||||
|
|
||||||
/* Setting signals_enabled and reading pending must
|
/*
|
||||||
|
* Setting signals_enabled and reading pending must
|
||||||
* happen in this order.
|
* happen in this order.
|
||||||
*/
|
*/
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
save_pending = pending;
|
save_pending = pending;
|
||||||
if (save_pending == 0) {
|
if (save_pending == 0) {
|
||||||
/* This must return with signals enabled, so
|
/*
|
||||||
|
* This must return with signals enabled, so
|
||||||
* this barrier ensures that writes are
|
* this barrier ensures that writes are
|
||||||
* flushed out before the return. This might
|
* flushed out before the return. This might
|
||||||
* matter if gcc figures out how to inline
|
* matter if gcc figures out how to inline
|
||||||
@@ -243,14 +247,16 @@ void unblock_signals(void)
|
|||||||
|
|
||||||
pending = 0;
|
pending = 0;
|
||||||
|
|
||||||
/* We have pending interrupts, so disable signals, as the
|
/*
|
||||||
|
* We have pending interrupts, so disable signals, as the
|
||||||
* handlers expect them off when they are called. They will
|
* handlers expect them off when they are called. They will
|
||||||
* be enabled again above.
|
* be enabled again above.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
signals_enabled = 0;
|
signals_enabled = 0;
|
||||||
|
|
||||||
/* Deal with SIGIO first because the alarm handler might
|
/*
|
||||||
|
* Deal with SIGIO first because the alarm handler might
|
||||||
* schedule, leaving the pending SIGIO stranded until we come
|
* schedule, leaving the pending SIGIO stranded until we come
|
||||||
* back here.
|
* back here.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,30 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
#include <stddef.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/wait.h>
|
#include "init.h"
|
||||||
#include <asm/unistd.h>
|
#include "kern_constants.h"
|
||||||
#include "mem_user.h"
|
#include "mm_id.h"
|
||||||
#include "mem.h"
|
|
||||||
#include "skas.h"
|
|
||||||
#include "user.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "proc_mm.h"
|
#include "proc_mm.h"
|
||||||
#include "ptrace_user.h"
|
#include "ptrace_user.h"
|
||||||
#include "kern_util.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "registers.h"
|
#include "registers.h"
|
||||||
#include "uml-config.h"
|
#include "skas.h"
|
||||||
|
#include "user.h"
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
#include "sysdep/stub.h"
|
#include "sysdep/stub.h"
|
||||||
#include "init.h"
|
#include "uml-config.h"
|
||||||
#include "kern_constants.h"
|
|
||||||
|
|
||||||
extern unsigned long batch_syscall_stub, __syscall_stub_start;
|
extern unsigned long batch_syscall_stub, __syscall_stub_start;
|
||||||
|
|
||||||
@@ -75,9 +70,9 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
|
|||||||
|
|
||||||
n = ptrace_setregs(pid, syscall_regs);
|
n = ptrace_setregs(pid, syscall_regs);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
printk("Registers - \n");
|
printk(UM_KERN_ERR "Registers - \n");
|
||||||
for (i = 0; i < MAX_REG_NR; i++)
|
for (i = 0; i < MAX_REG_NR; i++)
|
||||||
printk("\t%d\t0x%lx\n", i, syscall_regs[i]);
|
printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]);
|
||||||
panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
|
panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
|
||||||
-n);
|
-n);
|
||||||
}
|
}
|
||||||
@@ -89,7 +84,8 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
|
|||||||
|
|
||||||
wait_stub_done(pid);
|
wait_stub_done(pid);
|
||||||
|
|
||||||
/* When the stub stops, we find the following values on the
|
/*
|
||||||
|
* When the stub stops, we find the following values on the
|
||||||
* beginning of the stack:
|
* beginning of the stack:
|
||||||
* (long )return_value
|
* (long )return_value
|
||||||
* (long )offset to failed sycall-data (0, if no error)
|
* (long )offset to failed sycall-data (0, if no error)
|
||||||
@@ -99,21 +95,22 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
|
|||||||
if (offset) {
|
if (offset) {
|
||||||
data = (unsigned long *)(mm_idp->stack +
|
data = (unsigned long *)(mm_idp->stack +
|
||||||
offset - UML_CONFIG_STUB_DATA);
|
offset - UML_CONFIG_STUB_DATA);
|
||||||
printk("do_syscall_stub : ret = %ld, offset = %ld, "
|
printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, "
|
||||||
"data = %p\n", ret, offset, data);
|
"data = %p\n", ret, offset, data);
|
||||||
syscall = (unsigned long *)((unsigned long)data + data[0]);
|
syscall = (unsigned long *)((unsigned long)data + data[0]);
|
||||||
printk("do_syscall_stub: syscall %ld failed, return value = "
|
printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, "
|
||||||
"0x%lx, expected return value = 0x%lx\n",
|
"return value = 0x%lx, expected return value = 0x%lx\n",
|
||||||
syscall[0], ret, syscall[7]);
|
syscall[0], ret, syscall[7]);
|
||||||
printk(" syscall parameters: "
|
printk(UM_KERN_ERR " syscall parameters: "
|
||||||
"0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
|
"0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
|
||||||
syscall[1], syscall[2], syscall[3],
|
syscall[1], syscall[2], syscall[3],
|
||||||
syscall[4], syscall[5], syscall[6]);
|
syscall[4], syscall[5], syscall[6]);
|
||||||
for (n = 1; n < data[0]/sizeof(long); n++) {
|
for (n = 1; n < data[0]/sizeof(long); n++) {
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
printk(" additional syscall data:");
|
printk(UM_KERN_ERR " additional syscall "
|
||||||
|
"data:");
|
||||||
if (n % 4 == 1)
|
if (n % 4 == 1)
|
||||||
printk("\n ");
|
printk("\n" UM_KERN_ERR " ");
|
||||||
printk(" 0x%lx", data[n]);
|
printk(" 0x%lx", data[n]);
|
||||||
}
|
}
|
||||||
if (n > 1)
|
if (n > 1)
|
||||||
@@ -165,7 +162,8 @@ long syscall_stub_data(struct mm_id * mm_idp,
|
|||||||
unsigned long *stack;
|
unsigned long *stack;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* If *addr still is uninitialized, it *must* contain NULL.
|
/*
|
||||||
|
* If *addr still is uninitialized, it *must* contain NULL.
|
||||||
* Thus in this case do_syscall_stub correctly won't be called.
|
* Thus in this case do_syscall_stub correctly won't be called.
|
||||||
*/
|
*/
|
||||||
if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
|
if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
|
||||||
@@ -212,7 +210,8 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
|
|||||||
CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
|
CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
|
||||||
if (ret != sizeof(map)) {
|
if (ret != sizeof(map)) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
printk("map : /proc/mm map failed, err = %d\n", -ret);
|
printk(UM_KERN_ERR "map : /proc/mm map failed, "
|
||||||
|
"err = %d\n", -ret);
|
||||||
}
|
}
|
||||||
else ret = 0;
|
else ret = 0;
|
||||||
}
|
}
|
||||||
@@ -246,7 +245,8 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
|
|||||||
CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
|
CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
|
||||||
if (ret != sizeof(unmap)) {
|
if (ret != sizeof(unmap)) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
printk("unmap - proc_mm write returned %d\n", ret);
|
printk(UM_KERN_ERR "unmap - proc_mm write returned "
|
||||||
|
"%d\n", ret);
|
||||||
}
|
}
|
||||||
else ret = 0;
|
else ret = 0;
|
||||||
}
|
}
|
||||||
@@ -281,7 +281,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
|
|||||||
CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
|
CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
|
||||||
if (ret != sizeof(protect)) {
|
if (ret != sizeof(protect)) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
printk("protect failed, err = %d", -ret);
|
printk(UM_KERN_ERR "protect failed, err = %d", -ret);
|
||||||
}
|
}
|
||||||
else ret = 0;
|
else ret = 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,48 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include "ptrace_user.h"
|
#include <errno.h>
|
||||||
#include <sys/wait.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/user.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/time.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/syscall.h>
|
#include <asm/unistd.h>
|
||||||
#include <asm/types.h>
|
|
||||||
#include "user.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "skas.h"
|
|
||||||
#include "stub-data.h"
|
|
||||||
#include "mm_id.h"
|
|
||||||
#include "sysdep/sigcontext.h"
|
|
||||||
#include "sysdep/stub.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "proc_mm.h"
|
|
||||||
#include "skas_ptrace.h"
|
|
||||||
#include "chan_user.h"
|
|
||||||
#include "registers.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "uml-config.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "longjmp.h"
|
|
||||||
#include "kern_constants.h"
|
|
||||||
#include "as-layout.h"
|
#include "as-layout.h"
|
||||||
|
#include "chan_user.h"
|
||||||
|
#include "kern_constants.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "os.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "proc_mm.h"
|
||||||
|
#include "ptrace_user.h"
|
||||||
|
#include "registers.h"
|
||||||
|
#include "skas.h"
|
||||||
|
#include "skas_ptrace.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "sysdep/stub.h"
|
||||||
|
|
||||||
int is_skas_winch(int pid, int fd, void *data)
|
int is_skas_winch(int pid, int fd, void *data)
|
||||||
{
|
{
|
||||||
if (pid != os_getpgrp())
|
if (pid != os_getpgrp())
|
||||||
return(0);
|
return 0;
|
||||||
|
|
||||||
register_winch_irq(-1, fd, -1, data, 0);
|
register_winch_irq(-1, fd, -1, data, 0);
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptrace_dump_regs(int pid)
|
static int ptrace_dump_regs(int pid)
|
||||||
@@ -52,11 +42,10 @@ static int ptrace_dump_regs(int pid)
|
|||||||
|
|
||||||
if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
|
if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
else {
|
|
||||||
printk("Stub registers -\n");
|
printk(UM_KERN_ERR "Stub registers -\n");
|
||||||
for (i = 0; i < ARRAY_SIZE(regs); i++)
|
for (i = 0; i < ARRAY_SIZE(regs); i++)
|
||||||
printk("\t%d - %lx\n", i, regs[i]);
|
printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -94,7 +83,8 @@ void wait_stub_done(int pid)
|
|||||||
bad_wait:
|
bad_wait:
|
||||||
err = ptrace_dump_regs(pid);
|
err = ptrace_dump_regs(pid);
|
||||||
if (err)
|
if (err)
|
||||||
printk("Failed to get registers from stub, errno = %d\n", -err);
|
printk(UM_KERN_ERR "Failed to get registers from stub, "
|
||||||
|
"errno = %d\n", -err);
|
||||||
panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
|
panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
|
||||||
"n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
|
"n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
|
||||||
}
|
}
|
||||||
@@ -124,7 +114,8 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
|
|||||||
pid, errno);
|
pid, errno);
|
||||||
wait_stub_done(pid);
|
wait_stub_done(pid);
|
||||||
|
|
||||||
/* faultinfo is prepared by the stub-segv-handler at start of
|
/*
|
||||||
|
* faultinfo is prepared by the stub-segv-handler at start of
|
||||||
* the stub stack page. We just have to copy it.
|
* the stub stack page. We just have to copy it.
|
||||||
*/
|
*/
|
||||||
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
|
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
|
||||||
@@ -137,8 +128,12 @@ static void handle_segv(int pid, struct uml_pt_regs * regs)
|
|||||||
segv(regs->faultinfo, 0, 1, NULL);
|
segv(regs->faultinfo, 0, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
|
/*
|
||||||
static void handle_trap(int pid, struct uml_pt_regs *regs, int local_using_sysemu)
|
* To use the same value of using_sysemu as the caller, ask it that value
|
||||||
|
* (in local_using_sysemu
|
||||||
|
*/
|
||||||
|
static void handle_trap(int pid, struct uml_pt_regs *regs,
|
||||||
|
int local_using_sysemu)
|
||||||
{
|
{
|
||||||
int err, status;
|
int err, status;
|
||||||
|
|
||||||
@@ -150,21 +145,21 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, int local_using_sysem
|
|||||||
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
|
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
|
||||||
__NR_getpid);
|
__NR_getpid);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
panic("handle_trap - nullifying syscall failed errno = %d\n",
|
panic("handle_trap - nullifying syscall failed, "
|
||||||
errno);
|
"errno = %d\n", errno);
|
||||||
|
|
||||||
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
panic("handle_trap - continuing to end of syscall failed, "
|
panic("handle_trap - continuing to end of syscall "
|
||||||
"errno = %d\n", errno);
|
"failed, errno = %d\n", errno);
|
||||||
|
|
||||||
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
|
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
|
||||||
if ((err < 0) || !WIFSTOPPED(status) ||
|
if ((err < 0) || !WIFSTOPPED(status) ||
|
||||||
(WSTOPSIG(status) != SIGTRAP + 0x80)) {
|
(WSTOPSIG(status) != SIGTRAP + 0x80)) {
|
||||||
err = ptrace_dump_regs(pid);
|
err = ptrace_dump_regs(pid);
|
||||||
if (err)
|
if (err)
|
||||||
printk("Failed to get registers from process, "
|
printk(UM_KERN_ERR "Failed to get registers "
|
||||||
"errno = %d\n", -err);
|
"from process, errno = %d\n", -err);
|
||||||
panic("handle_trap - failed to wait at end of syscall, "
|
panic("handle_trap - failed to wait at end of syscall, "
|
||||||
"errno = %d, status = %d\n", errno, status);
|
"errno = %d, status = %d\n", errno, status);
|
||||||
}
|
}
|
||||||
@@ -189,17 +184,18 @@ static int userspace_tramp(void *stack)
|
|||||||
err);
|
err);
|
||||||
|
|
||||||
if (!proc_mm) {
|
if (!proc_mm) {
|
||||||
/* This has a pte, but it can't be mapped in with the usual
|
/*
|
||||||
|
* This has a pte, but it can't be mapped in with the usual
|
||||||
* tlb_flush mechanism because this is part of that mechanism
|
* tlb_flush mechanism because this is part of that mechanism
|
||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
__u64 offset;
|
unsigned long long offset;
|
||||||
fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
|
fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
|
||||||
addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
|
addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
|
||||||
PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
|
PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
|
||||||
if (addr == MAP_FAILED) {
|
if (addr == MAP_FAILED) {
|
||||||
printk("mapping mmap stub failed, errno = %d\n",
|
printk(UM_KERN_ERR "mapping mmap stub failed, "
|
||||||
errno);
|
"errno = %d\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,8 +205,8 @@ static int userspace_tramp(void *stack)
|
|||||||
UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||||
MAP_FIXED | MAP_SHARED, fd, offset);
|
MAP_FIXED | MAP_SHARED, fd, offset);
|
||||||
if (addr == MAP_FAILED) {
|
if (addr == MAP_FAILED) {
|
||||||
printk("mapping segfault stack failed, "
|
printk(UM_KERN_ERR "mapping segfault stack "
|
||||||
"errno = %d\n", errno);
|
"failed, errno = %d\n", errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +234,7 @@ static int userspace_tramp(void *stack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
os_stop_process(os_getpid());
|
os_stop_process(os_getpid());
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Each element set once, and only accessed by a single processor anyway */
|
/* Each element set once, and only accessed by a single processor anyway */
|
||||||
@@ -260,7 +256,9 @@ int start_userspace(unsigned long stub_stack)
|
|||||||
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
|
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
|
||||||
|
|
||||||
flags = CLONE_FILES | SIGCHLD;
|
flags = CLONE_FILES | SIGCHLD;
|
||||||
if(proc_mm) flags |= CLONE_VM;
|
if (proc_mm)
|
||||||
|
flags |= CLONE_VM;
|
||||||
|
|
||||||
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
|
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
panic("start_userspace : clone failed, errno = %d", errno);
|
panic("start_userspace : clone failed, errno = %d", errno);
|
||||||
@@ -276,14 +274,15 @@ int start_userspace(unsigned long stub_stack)
|
|||||||
panic("start_userspace : expected SIGSTOP, got status = %d",
|
panic("start_userspace : expected SIGSTOP, got status = %d",
|
||||||
status);
|
status);
|
||||||
|
|
||||||
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
|
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
|
||||||
panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
|
(void *) PTRACE_O_TRACESYSGOOD) < 0)
|
||||||
errno);
|
panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
|
||||||
|
"errno = %d\n", errno);
|
||||||
|
|
||||||
if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
|
if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
|
||||||
panic("start_userspace : munmap failed, errno = %d\n", errno);
|
panic("start_userspace : munmap failed, errno = %d\n", errno);
|
||||||
|
|
||||||
return(pid);
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void userspace(struct uml_pt_regs *regs)
|
void userspace(struct uml_pt_regs *regs)
|
||||||
@@ -320,8 +319,10 @@ void userspace(struct uml_pt_regs *regs)
|
|||||||
int sig = WSTOPSIG(status);
|
int sig = WSTOPSIG(status);
|
||||||
switch(sig) {
|
switch(sig) {
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
|
if (PTRACE_FULL_FAULTINFO ||
|
||||||
get_skas_faultinfo(pid, ®s->faultinfo);
|
!ptrace_faultinfo) {
|
||||||
|
get_skas_faultinfo(pid,
|
||||||
|
®s->faultinfo);
|
||||||
(*sig_info[SIGSEGV])(SIGSEGV, regs);
|
(*sig_info[SIGSEGV])(SIGSEGV, regs);
|
||||||
}
|
}
|
||||||
else handle_segv(pid, regs);
|
else handle_segv(pid, regs);
|
||||||
@@ -343,8 +344,8 @@ void userspace(struct uml_pt_regs *regs)
|
|||||||
unblock_signals();
|
unblock_signals();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("userspace - child stopped with signal "
|
printk(UM_KERN_ERR "userspace - child stopped "
|
||||||
"%d\n", sig);
|
"with signal %d\n", sig);
|
||||||
}
|
}
|
||||||
pid = userspace_pid[0];
|
pid = userspace_pid[0];
|
||||||
interrupt_end();
|
interrupt_end();
|
||||||
@@ -384,7 +385,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
|
|||||||
__u64 new_offset;
|
__u64 new_offset;
|
||||||
int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
|
int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
|
||||||
|
|
||||||
/* prepare offset and fd of child's stack as argument for parent's
|
/*
|
||||||
|
* prepare offset and fd of child's stack as argument for parent's
|
||||||
* and child's mmap2 calls
|
* and child's mmap2 calls
|
||||||
*/
|
*/
|
||||||
*data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
|
*data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
|
||||||
@@ -400,7 +402,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
|
|||||||
/* set a well known return code for detection of child write failure */
|
/* set a well known return code for detection of child write failure */
|
||||||
child_data->err = 12345678;
|
child_data->err = 12345678;
|
||||||
|
|
||||||
/* Wait, until parent has finished its work: read child's pid from
|
/*
|
||||||
|
* Wait, until parent has finished its work: read child's pid from
|
||||||
* parent's stack, and check, if bad result.
|
* parent's stack, and check, if bad result.
|
||||||
*/
|
*/
|
||||||
err = ptrace(PTRACE_CONT, pid, 0, 0);
|
err = ptrace(PTRACE_CONT, pid, 0, 0);
|
||||||
@@ -414,7 +417,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
|
|||||||
panic("copy_context_skas0 - stub-parent reports error %d\n",
|
panic("copy_context_skas0 - stub-parent reports error %d\n",
|
||||||
-pid);
|
-pid);
|
||||||
|
|
||||||
/* Wait, until child has finished too: read child's result from
|
/*
|
||||||
|
* Wait, until child has finished too: read child's result from
|
||||||
* child's stack and check it.
|
* child's stack and check it.
|
||||||
*/
|
*/
|
||||||
wait_stub_done(pid);
|
wait_stub_done(pid);
|
||||||
@@ -457,8 +461,9 @@ void map_stub_pages(int fd, unsigned long code,
|
|||||||
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
|
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
|
||||||
if (n != sizeof(mmop)) {
|
if (n != sizeof(mmop)) {
|
||||||
n = errno;
|
n = errno;
|
||||||
printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
|
printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
|
||||||
code, code_fd, (unsigned long long) code_offset);
|
"offset = %llx\n", code, code_fd,
|
||||||
|
(unsigned long long) code_offset);
|
||||||
panic("map_stub_pages : /proc/mm map for code failed, "
|
panic("map_stub_pages : /proc/mm map for code failed, "
|
||||||
"err = %d\n", n);
|
"err = %d\n", n);
|
||||||
}
|
}
|
||||||
@@ -538,10 +543,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
|
|||||||
break;
|
break;
|
||||||
case INIT_JMP_HALT:
|
case INIT_JMP_HALT:
|
||||||
kmalloc_ok = 0;
|
kmalloc_ok = 0;
|
||||||
return(0);
|
return 0;
|
||||||
case INIT_JMP_REBOOT:
|
case INIT_JMP_REBOOT:
|
||||||
kmalloc_ok = 0;
|
kmalloc_ok = 0;
|
||||||
return(1);
|
return 1;
|
||||||
default:
|
default:
|
||||||
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
|
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
#if 0
|
||||||
#include <errno.h>
|
|
||||||
#include "kern_util.h"
|
#include "kern_util.h"
|
||||||
#include "as-layout.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "sigcontext.h"
|
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
#include "ptrace_user.h"
|
#include "ptrace_user.h"
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "sysdep/ptrace_user.h"
|
#include "sysdep/ptrace_user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "sysdep/ptrace.h"
|
||||||
|
#include "kern_constants.h"
|
||||||
|
#include "as-layout.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "sigcontext.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
|
static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
|
||||||
|
|
||||||
@@ -24,14 +28,16 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
|
|||||||
void (*handler)(int, struct uml_pt_regs *);
|
void (*handler)(int, struct uml_pt_regs *);
|
||||||
int save_user, save_errno = errno;
|
int save_user, save_errno = errno;
|
||||||
|
|
||||||
/* This is done because to allow SIGSEGV to be delivered inside a SEGV
|
/*
|
||||||
|
* This is done because to allow SIGSEGV to be delivered inside a SEGV
|
||||||
* handler. This can happen in copy_user, and if SEGV is disabled,
|
* handler. This can happen in copy_user, and if SEGV is disabled,
|
||||||
* the process will die.
|
* the process will die.
|
||||||
* XXX Figure out why this is better than SA_NODEFER
|
* XXX Figure out why this is better than SA_NODEFER
|
||||||
*/
|
*/
|
||||||
if (sig == SIGSEGV) {
|
if (sig == SIGSEGV) {
|
||||||
change_sig(SIGSEGV, 1);
|
change_sig(SIGSEGV, 1);
|
||||||
/* For segfaults, we want the data from the
|
/*
|
||||||
|
* For segfaults, we want the data from the
|
||||||
* sigcontext. In this case, we don't want to mangle
|
* sigcontext. In this case, we don't want to mangle
|
||||||
* the process registers, so use a static set of
|
* the process registers, so use a static set of
|
||||||
* registers. For other signals, the process
|
* registers. For other signals, the process
|
||||||
@@ -44,11 +50,9 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
|
|||||||
|
|
||||||
save_user = r->is_user;
|
save_user = r->is_user;
|
||||||
r->is_user = 0;
|
r->is_user = 0;
|
||||||
if ( sig == SIGFPE || sig == SIGSEGV ||
|
if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
|
||||||
sig == SIGBUS || sig == SIGILL ||
|
(sig == SIGILL) || (sig == SIGTRAP))
|
||||||
sig == SIGTRAP ) {
|
|
||||||
GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
|
GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
|
||||||
}
|
|
||||||
|
|
||||||
change_sig(SIGUSR1, 1);
|
change_sig(SIGUSR1, 1);
|
||||||
|
|
||||||
|
@@ -1,41 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pty.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/time.h>
|
#include <fcntl.h>
|
||||||
#include <sys/wait.h>
|
#include <sched.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "user.h"
|
|
||||||
#include "signal_kern.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "sysdep/sigcontext.h"
|
|
||||||
#include "irq_user.h"
|
|
||||||
#include "ptrace_user.h"
|
|
||||||
#include "mem_user.h"
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "os.h"
|
|
||||||
#include "uml-config.h"
|
|
||||||
#include "tempfile.h"
|
|
||||||
#include "kern_constants.h"
|
#include "kern_constants.h"
|
||||||
#include "skas.h"
|
#include "os.h"
|
||||||
#include "skas_ptrace.h"
|
#include "mem_user.h"
|
||||||
|
#include "ptrace_user.h"
|
||||||
#include "registers.h"
|
#include "registers.h"
|
||||||
|
#include "skas_ptrace.h"
|
||||||
|
|
||||||
static int ptrace_child(void *arg)
|
static int ptrace_child(void *arg)
|
||||||
{
|
{
|
||||||
@@ -50,20 +38,27 @@ static int ptrace_child(void *arg)
|
|||||||
}
|
}
|
||||||
kill(pid, SIGSTOP);
|
kill(pid, SIGSTOP);
|
||||||
|
|
||||||
/*This syscall will be intercepted by the parent. Don't call more than
|
/*
|
||||||
* once, please.*/
|
* This syscall will be intercepted by the parent. Don't call more than
|
||||||
|
* once, please.
|
||||||
|
*/
|
||||||
sc_result = os_getpid();
|
sc_result = os_getpid();
|
||||||
|
|
||||||
if (sc_result == pid)
|
if (sc_result == pid)
|
||||||
ret = 1; /*Nothing modified by the parent, we are running
|
/* Nothing modified by the parent, we are running normally. */
|
||||||
normally.*/
|
ret = 1;
|
||||||
else if (sc_result == ppid)
|
else if (sc_result == ppid)
|
||||||
ret = 0; /*Expected in check_ptrace and check_sysemu when they
|
/*
|
||||||
succeed in modifying the stack frame*/
|
* Expected in check_ptrace and check_sysemu when they succeed
|
||||||
|
* in modifying the stack frame
|
||||||
|
*/
|
||||||
|
ret = 0;
|
||||||
else
|
else
|
||||||
ret = 2; /*Serious trouble! This could be caused by a bug in
|
/* Serious trouble! This could be caused by a bug in host 2.6
|
||||||
host 2.6 SKAS3/2.6 patch before release -V6, together
|
* SKAS3/2.6 patch before release -V6, together with a bug in
|
||||||
with a bug in the UML code itself.*/
|
* the UML code itself.
|
||||||
|
*/
|
||||||
|
ret = 2;
|
||||||
_exit(ret);
|
_exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,10 +101,12 @@ static int start_ptraced_child(void **stack_out)
|
|||||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
if (stack == MAP_FAILED)
|
if (stack == MAP_FAILED)
|
||||||
fatal_perror("check_ptrace : mmap failed");
|
fatal_perror("check_ptrace : mmap failed");
|
||||||
|
|
||||||
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
|
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
|
||||||
pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
|
pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
fatal_perror("start_ptraced_child : clone failed");
|
fatal_perror("start_ptraced_child : clone failed");
|
||||||
|
|
||||||
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
|
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
fatal_perror("check_ptrace : clone failed");
|
fatal_perror("check_ptrace : clone failed");
|
||||||
@@ -256,7 +253,8 @@ static void __init check_sysemu(void)
|
|||||||
if (n < 0)
|
if (n < 0)
|
||||||
fatal_perror("check_ptrace : wait failed");
|
fatal_perror("check_ptrace : wait failed");
|
||||||
|
|
||||||
if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
|
if (WIFSTOPPED(status) &&
|
||||||
|
(WSTOPSIG(status) == (SIGTRAP|0x80))) {
|
||||||
if (!count)
|
if (!count)
|
||||||
fatal("check_ptrace : SYSEMU_SINGLESTEP "
|
fatal("check_ptrace : SYSEMU_SINGLESTEP "
|
||||||
"doesn't singlestep");
|
"doesn't singlestep");
|
||||||
@@ -477,12 +475,9 @@ static inline void check_skas3_proc_mm(void)
|
|||||||
proc_mm = 0;
|
proc_mm = 0;
|
||||||
perror("not found");
|
perror("not found");
|
||||||
}
|
}
|
||||||
else {
|
else if (!proc_mm)
|
||||||
if (!proc_mm)
|
|
||||||
non_fatal("found but disabled on command line\n");
|
non_fatal("found but disabled on command line\n");
|
||||||
else
|
else non_fatal("found\n");
|
||||||
non_fatal("found\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_do_skas(void)
|
int can_do_skas(void)
|
||||||
|
@@ -1,13 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "kern_util.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "longjmp.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
|
||||||
/* Initialized from linux_main() */
|
/* Initialized from linux_main() */
|
||||||
void (*sig_info[NSIG])(int, struct uml_pt_regs *);
|
void (*sig_info[NSIG])(int, struct uml_pt_regs *);
|
||||||
|
@@ -1,14 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
|
* Licensed under the GPL
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/fcntl.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "kern_constants.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
@@ -32,8 +37,8 @@ static int __init make_uml_dir(void)
|
|||||||
|
|
||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
if (home == NULL) {
|
if (home == NULL) {
|
||||||
printk("make_uml_dir : no value in environment for "
|
printk(UM_KERN_ERR "make_uml_dir : no value in "
|
||||||
"$HOME\n");
|
"environment for $HOME\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
strlcpy(dir, home, sizeof(dir));
|
strlcpy(dir, home, sizeof(dir));
|
||||||
@@ -69,8 +74,8 @@ err:
|
|||||||
/*
|
/*
|
||||||
* Unlinks the files contained in @dir and then removes @dir.
|
* Unlinks the files contained in @dir and then removes @dir.
|
||||||
* Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
|
* Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
|
||||||
* ignore ENOENT errors for anything (they happen, strangely enough - possibly due
|
* ignore ENOENT errors for anything (they happen, strangely enough - possibly
|
||||||
* to races between multiple dying UML threads).
|
* due to races between multiple dying UML threads).
|
||||||
*/
|
*/
|
||||||
static int remove_files_and_dir(char *dir)
|
static int remove_files_and_dir(char *dir)
|
||||||
{
|
{
|
||||||
@@ -115,7 +120,8 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This says that there isn't already a user of the specified directory even if
|
/*
|
||||||
|
* This says that there isn't already a user of the specified directory even if
|
||||||
* there are errors during the checking. This is because if these errors
|
* there are errors during the checking. This is because if these errors
|
||||||
* happen, the directory is unusable by the pre-existing UML, so we might as
|
* happen, the directory is unusable by the pre-existing UML, so we might as
|
||||||
* well take it over. This could happen either by
|
* well take it over. This could happen either by
|
||||||
@@ -134,7 +140,7 @@ static inline int is_umdir_used(char *dir)
|
|||||||
|
|
||||||
n = snprintf(file, sizeof(file), "%s/pid", dir);
|
n = snprintf(file, sizeof(file), "%s/pid", dir);
|
||||||
if (n >= sizeof(file)) {
|
if (n >= sizeof(file)) {
|
||||||
printk("is_umdir_used - pid filename too long\n");
|
printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n");
|
||||||
err = -E2BIG;
|
err = -E2BIG;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -144,8 +150,8 @@ static inline int is_umdir_used(char *dir)
|
|||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fd = -errno;
|
fd = -errno;
|
||||||
if (fd != -ENOENT) {
|
if (fd != -ENOENT) {
|
||||||
printk("is_umdir_used : couldn't open pid file '%s', "
|
printk(UM_KERN_ERR "is_umdir_used : couldn't open pid "
|
||||||
"err = %d\n", file, -fd);
|
"file '%s', err = %d\n", file, -fd);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -153,24 +159,25 @@ static inline int is_umdir_used(char *dir)
|
|||||||
err = 0;
|
err = 0;
|
||||||
n = read(fd, pid, sizeof(pid));
|
n = read(fd, pid, sizeof(pid));
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
printk("is_umdir_used : couldn't read pid file '%s', "
|
printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
|
||||||
"err = %d\n", file, errno);
|
"'%s', err = %d\n", file, errno);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
} else if (n == 0) {
|
} else if (n == 0) {
|
||||||
printk("is_umdir_used : couldn't read pid file '%s', "
|
printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
|
||||||
"0-byte read\n", file);
|
"'%s', 0-byte read\n", file);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strtoul(pid, &end, 0);
|
p = strtoul(pid, &end, 0);
|
||||||
if (end == pid) {
|
if (end == pid) {
|
||||||
printk("is_umdir_used : couldn't parse pid file '%s', "
|
printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file "
|
||||||
"errno = %d\n", file, errno);
|
"'%s', errno = %d\n", file, errno);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((kill(p, 0) == 0) || (errno != ESRCH)) {
|
if ((kill(p, 0) == 0) || (errno != ESRCH)) {
|
||||||
printk("umid \"%s\" is already in use by pid %d\n", umid, p);
|
printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n",
|
||||||
|
umid, p);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,8 +201,8 @@ static int umdir_take_if_dead(char *dir)
|
|||||||
|
|
||||||
ret = remove_files_and_dir(dir);
|
ret = remove_files_and_dir(dir);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("is_umdir_used - remove_files_and_dir failed with "
|
printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir "
|
||||||
"err = %d\n", ret);
|
"failed with err = %d\n", ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -211,15 +218,16 @@ static void __init create_pid_file(void)
|
|||||||
|
|
||||||
fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
|
fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("Open of machine pid file \"%s\" failed: %s\n",
|
printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: "
|
||||||
file, strerror(errno));
|
"%s\n", file, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(pid, sizeof(pid), "%d\n", getpid());
|
snprintf(pid, sizeof(pid), "%d\n", getpid());
|
||||||
n = write(fd, pid, strlen(pid));
|
n = write(fd, pid, strlen(pid));
|
||||||
if (n != strlen(pid))
|
if (n != strlen(pid))
|
||||||
printk("Write of pid file failed - err = %d\n", errno);
|
printk(UM_KERN_ERR "Write of pid file failed - err = %d\n",
|
||||||
|
errno);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@@ -252,8 +260,8 @@ int __init make_umid(void)
|
|||||||
strlcat(tmp, "XXXXXX", sizeof(tmp));
|
strlcat(tmp, "XXXXXX", sizeof(tmp));
|
||||||
fd = mkstemp(tmp);
|
fd = mkstemp(tmp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("make_umid - mkstemp(%s) failed: %s\n",
|
printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: "
|
||||||
tmp, strerror(errno));
|
"%s\n", tmp, strerror(errno));
|
||||||
err = -errno;
|
err = -errno;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -262,7 +270,8 @@ int __init make_umid(void)
|
|||||||
|
|
||||||
set_umid(&tmp[strlen(uml_dir)]);
|
set_umid(&tmp[strlen(uml_dir)]);
|
||||||
|
|
||||||
/* There's a nice tiny little race between this unlink and
|
/*
|
||||||
|
* There's a nice tiny little race between this unlink and
|
||||||
* the mkdir below. It'd be nice if there were a mkstemp
|
* the mkdir below. It'd be nice if there were a mkstemp
|
||||||
* for directories.
|
* for directories.
|
||||||
*/
|
*/
|
||||||
@@ -286,7 +295,8 @@ int __init make_umid(void)
|
|||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
printk("Failed to create '%s' - err = %d\n", umid, -errno);
|
printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid,
|
||||||
|
errno);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,11 +314,12 @@ static int __init make_umid_init(void)
|
|||||||
if (!make_umid())
|
if (!make_umid())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If initializing with the given umid failed, then try again with
|
/*
|
||||||
|
* If initializing with the given umid failed, then try again with
|
||||||
* a random one.
|
* a random one.
|
||||||
*/
|
*/
|
||||||
printk("Failed to initialize umid \"%s\", trying with a random umid\n",
|
printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a "
|
||||||
umid);
|
"random umid\n", umid);
|
||||||
*umid = '\0';
|
*umid = '\0';
|
||||||
make_umid();
|
make_umid();
|
||||||
|
|
||||||
@@ -327,7 +338,7 @@ int __init umid_file_name(char *name, char *buf, int len)
|
|||||||
|
|
||||||
n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
|
n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
|
||||||
if (n >= len) {
|
if (n >= len) {
|
||||||
printk("umid_file_name : buffer too short\n");
|
printk(UM_KERN_ERR "umid_file_name : buffer too short\n");
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +366,8 @@ static int __init set_uml_dir(char *name, int *add)
|
|||||||
if (uml_dir == NULL) {
|
if (uml_dir == NULL) {
|
||||||
printf("Failed to malloc uml_dir - error = %d\n", errno);
|
printf("Failed to malloc uml_dir - error = %d\n", errno);
|
||||||
|
|
||||||
/* Return 0 here because do_initcalls doesn't look at
|
/*
|
||||||
|
* Return 0 here because do_initcalls doesn't look at
|
||||||
* the return value.
|
* the return value.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -1,18 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/signal.h>
|
#include "kern_constants.h"
|
||||||
#include <asm/ldt.h>
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "user.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
#define MAXTOKEN 64
|
#define MAXTOKEN 64
|
||||||
|
|
||||||
@@ -33,7 +30,8 @@ static char token(int fd, char *buf, int len, char stop)
|
|||||||
if (n != sizeof(*ptr)) {
|
if (n != sizeof(*ptr)) {
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0;
|
return 0;
|
||||||
printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
|
printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
|
||||||
|
"err = %d\n", -n);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return n;
|
return n;
|
||||||
else return -EIO;
|
else return -EIO;
|
||||||
@@ -41,7 +39,8 @@ static char token(int fd, char *buf, int len, char stop)
|
|||||||
} while ((c != '\n') && (c != stop) && (ptr < end));
|
} while ((c != '\n') && (c != stop) && (ptr < end));
|
||||||
|
|
||||||
if (ptr == end) {
|
if (ptr == end) {
|
||||||
printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
|
printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
|
||||||
|
stop);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*(ptr - 1) = '\0';
|
*(ptr - 1) = '\0';
|
||||||
@@ -59,7 +58,8 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
|
|||||||
if (c <= 0)
|
if (c <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (c != ':') {
|
else if (c != ':') {
|
||||||
printk("Failed to find ':' in /proc/cpuinfo\n");
|
printk(UM_KERN_ERR "Failed to find ':' in "
|
||||||
|
"/proc/cpuinfo\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
|
|||||||
do {
|
do {
|
||||||
n = os_read_file(fd, &c, sizeof(c));
|
n = os_read_file(fd, &c, sizeof(c));
|
||||||
if (n != sizeof(c)) {
|
if (n != sizeof(c)) {
|
||||||
printk("Failed to find newline in "
|
printk(UM_KERN_ERR "Failed to find newline in "
|
||||||
"/proc/cpuinfo, err = %d\n", -n);
|
"/proc/cpuinfo, err = %d\n", -n);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -83,10 +83,12 @@ static int check_cpu_flag(char *feature, int *have_it)
|
|||||||
char buf[MAXTOKEN], c;
|
char buf[MAXTOKEN], c;
|
||||||
int fd, len = ARRAY_SIZE(buf);
|
int fd, len = ARRAY_SIZE(buf);
|
||||||
|
|
||||||
printk("Checking for host processor %s support...", feature);
|
printk(UM_KERN_INFO "Checking for host processor %s support...",
|
||||||
|
feature);
|
||||||
fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
|
fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
|
printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
|
||||||
|
-fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ static int check_cpu_flag(char *feature, int *have_it)
|
|||||||
if (c < 0)
|
if (c < 0)
|
||||||
goto out;
|
goto out;
|
||||||
else if (c != ' ') {
|
else if (c != ' ') {
|
||||||
printk("Failed to find ' ' in /proc/cpuinfo\n");
|
printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +108,8 @@ static int check_cpu_flag(char *feature, int *have_it)
|
|||||||
c = token(fd, buf, len - 1, ' ');
|
c = token(fd, buf, len - 1, ' ');
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
goto out;
|
goto out;
|
||||||
else if(c == '\n') break;
|
else if (c == '\n')
|
||||||
|
break;
|
||||||
|
|
||||||
if (!strcmp(buf, feature)) {
|
if (!strcmp(buf, feature)) {
|
||||||
*have_it = 1;
|
*have_it = 1;
|
||||||
@@ -122,7 +125,8 @@ static int check_cpu_flag(char *feature, int *have_it)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
|
#if 0 /*
|
||||||
|
* This doesn't work in tt mode, plus it's causing compilation problems
|
||||||
* for some people.
|
* for some people.
|
||||||
*/
|
*/
|
||||||
static void disable_lcall(void)
|
static void disable_lcall(void)
|
||||||
@@ -136,7 +140,8 @@ static void disable_lcall(void)
|
|||||||
ldt.limit = 0;
|
ldt.limit = 0;
|
||||||
err = modify_ldt(1, &ldt, sizeof(ldt));
|
err = modify_ldt(1, &ldt, sizeof(ldt));
|
||||||
if (err)
|
if (err)
|
||||||
printk("Failed to disable lcall7 - errno = %d\n", errno);
|
printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
|
||||||
|
errno);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -152,8 +157,8 @@ void arch_check_bugs(void)
|
|||||||
int have_it;
|
int have_it;
|
||||||
|
|
||||||
if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
|
if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
|
||||||
printk("/proc/cpuinfo not available - skipping CPU capability "
|
printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
|
||||||
"checks\n");
|
"capability checks\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (check_cpu_flag("cmov", &have_it))
|
if (check_cpu_flag("cmov", &have_it))
|
||||||
@@ -166,7 +171,8 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
|
|||||||
{
|
{
|
||||||
unsigned char tmp[2];
|
unsigned char tmp[2];
|
||||||
|
|
||||||
/* This is testing for a cmov (0x0f 0x4x) instruction causing a
|
/*
|
||||||
|
* This is testing for a cmov (0x0f 0x4x) instruction causing a
|
||||||
* SIGILL in init.
|
* SIGILL in init.
|
||||||
*/
|
*/
|
||||||
if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
|
if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
|
|||||||
fixup = search_exception_tables(address);
|
fixup = search_exception_tables(address);
|
||||||
if (fixup != 0) {
|
if (fixup != 0) {
|
||||||
UPT_IP(regs) = fixup->fixup;
|
UPT_IP(regs) = fixup->fixup;
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,26 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
#include "linux/mm.h"
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "linux/errno.h"
|
|
||||||
#include "linux/spinlock.h"
|
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "asm/smp.h"
|
|
||||||
#include "asm/ldt.h"
|
|
||||||
#include "asm/unistd.h"
|
#include "asm/unistd.h"
|
||||||
#include "kern.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "proc_mm.h"
|
||||||
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
|
|
||||||
|
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
#include "skas_ptrace.h"
|
#include "skas_ptrace.h"
|
||||||
#include "asm/mmu_context.h"
|
#include "sysdep/tls.h"
|
||||||
#include "proc_mm.h"
|
|
||||||
|
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
|
||||||
|
|
||||||
long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
|
long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
|
||||||
void **addr, int done)
|
void **addr, int done)
|
||||||
@@ -28,7 +19,8 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
|
|||||||
long res;
|
long res;
|
||||||
|
|
||||||
if (proc_mm) {
|
if (proc_mm) {
|
||||||
/* This is a special handling for the case, that the mm to
|
/*
|
||||||
|
* This is a special handling for the case, that the mm to
|
||||||
* modify isn't current->active_mm.
|
* modify isn't current->active_mm.
|
||||||
* If this is called directly by modify_ldt,
|
* If this is called directly by modify_ldt,
|
||||||
* (current->active_mm->context.skas.u == mm_idp)
|
* (current->active_mm->context.skas.u == mm_idp)
|
||||||
@@ -82,7 +74,8 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (proc_mm) {
|
if (proc_mm) {
|
||||||
/* This is the second part of special handling, that makes
|
/*
|
||||||
|
* This is the second part of special handling, that makes
|
||||||
* PTRACE_LDT possible to implement.
|
* PTRACE_LDT possible to implement.
|
||||||
*/
|
*/
|
||||||
if (current->active_mm && current->active_mm != &init_mm &&
|
if (current->active_mm && current->active_mm != &init_mm &&
|
||||||
@@ -105,7 +98,8 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
|
|||||||
if (ptrace_ldt.ptr == NULL)
|
if (ptrace_ldt.ptr == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* This is called from sys_modify_ldt only, so userspace_pid gives
|
/*
|
||||||
|
* This is called from sys_modify_ldt only, so userspace_pid gives
|
||||||
* us the right number
|
* us the right number
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -149,9 +143,8 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
|
|||||||
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
|
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
|
||||||
err = bytecount;
|
err = bytecount;
|
||||||
|
|
||||||
if(ptrace_ldt){
|
if (ptrace_ldt)
|
||||||
return read_ldt_from_host(ptr, bytecount);
|
return read_ldt_from_host(ptr, bytecount);
|
||||||
}
|
|
||||||
|
|
||||||
down(&ldt->semaphore);
|
down(&ldt->semaphore);
|
||||||
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
|
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
|
||||||
@@ -197,7 +190,8 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
|
|||||||
bytecount = 5*LDT_ENTRY_SIZE;
|
bytecount = 5*LDT_ENTRY_SIZE;
|
||||||
|
|
||||||
err = bytecount;
|
err = bytecount;
|
||||||
/* UML doesn't support lcall7 and lcall27.
|
/*
|
||||||
|
* UML doesn't support lcall7 and lcall27.
|
||||||
* So, we don't really have a default ldt, but emulate
|
* So, we don't really have a default ldt, but emulate
|
||||||
* an empty ldt of common host default ldt size.
|
* an empty ldt of common host default ldt size.
|
||||||
*/
|
*/
|
||||||
@@ -340,19 +334,20 @@ static void ldt_get_host_info(void)
|
|||||||
|
|
||||||
spin_unlock(&host_ldt_lock);
|
spin_unlock(&host_ldt_lock);
|
||||||
|
|
||||||
for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
|
for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
|
||||||
|
;
|
||||||
|
|
||||||
ldt = (struct ldt_entry *)
|
ldt = (struct ldt_entry *)
|
||||||
__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
|
__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
|
||||||
if (ldt == NULL) {
|
if (ldt == NULL) {
|
||||||
printk("ldt_get_host_info: couldn't allocate buffer for host "
|
printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
|
||||||
"ldt\n");
|
"for host ldt\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
|
ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk("ldt_get_host_info: couldn't read host ldt\n");
|
printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
@@ -372,18 +367,17 @@ static void ldt_get_host_info(void)
|
|||||||
size = (size + 1) * sizeof(dummy_list[0]);
|
size = (size + 1) * sizeof(dummy_list[0]);
|
||||||
tmp = kmalloc(size, GFP_KERNEL);
|
tmp = kmalloc(size, GFP_KERNEL);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
printk("ldt_get_host_info: couldn't allocate host ldt "
|
printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
|
||||||
"list\n");
|
"host ldt list\n");
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
host_ldt_entries = tmp;
|
host_ldt_entries = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
|
for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
|
||||||
if(ldt[i].a != 0 || ldt[i].b != 0) {
|
if (ldt[i].a != 0 || ldt[i].b != 0)
|
||||||
host_ldt_entries[k++] = i;
|
host_ldt_entries[k++] = i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
host_ldt_entries[k] = -1;
|
host_ldt_entries[k] = -1;
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
@@ -417,8 +411,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
|
|||||||
* To remove these gates, we simply write an empty
|
* To remove these gates, we simply write an empty
|
||||||
* entry as number 0 to the host.
|
* entry as number 0 to the host.
|
||||||
*/
|
*/
|
||||||
err = write_ldt_entry(&new_mm->id, 1, &desc,
|
err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
|
||||||
&addr, 1);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
/*
|
/*
|
||||||
@@ -441,7 +434,8 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (proc_mm) {
|
if (proc_mm) {
|
||||||
/* We have a valid from_mm, so we now have to copy the LDT of
|
/*
|
||||||
|
* We have a valid from_mm, so we now have to copy the LDT of
|
||||||
* from_mm to new_mm, because using proc_mm an new mm with
|
* from_mm to new_mm, because using proc_mm an new mm with
|
||||||
* an empty/default LDT was created in new_mm()
|
* an empty/default LDT was created in new_mm()
|
||||||
*/
|
*/
|
||||||
@@ -451,21 +445,21 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
|
|||||||
from_mm->id.u.mm_fd } } );
|
from_mm->id.u.mm_fd } } );
|
||||||
i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy));
|
i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy));
|
||||||
if (i != sizeof(copy))
|
if (i != sizeof(copy))
|
||||||
printk("new_mm : /proc/mm copy_segments failed, "
|
printk(KERN_ERR "new_mm : /proc/mm copy_segments "
|
||||||
"err = %d\n", -i);
|
"failed, err = %d\n", -i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ptrace_ldt) {
|
if (!ptrace_ldt) {
|
||||||
/* Our local LDT is used to supply the data for
|
/*
|
||||||
|
* Our local LDT is used to supply the data for
|
||||||
* modify_ldt(READLDT), if PTRACE_LDT isn't available,
|
* modify_ldt(READLDT), if PTRACE_LDT isn't available,
|
||||||
* i.e., we have to use the stub for modify_ldt, which
|
* i.e., we have to use the stub for modify_ldt, which
|
||||||
* can't handle the big read buffer of up to 64kB.
|
* can't handle the big read buffer of up to 64kB.
|
||||||
*/
|
*/
|
||||||
down(&from_mm->ldt.semaphore);
|
down(&from_mm->ldt.semaphore);
|
||||||
if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
|
if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
|
||||||
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
|
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
|
||||||
sizeof(new_mm->ldt.u.entries));
|
sizeof(new_mm->ldt.u.entries));
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
|
i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
|
||||||
while (i-->0) {
|
while (i-->0) {
|
||||||
@@ -495,10 +489,9 @@ void free_ldt(struct mmu_context_skas * mm)
|
|||||||
|
|
||||||
if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
|
if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
|
||||||
i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
|
i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
|
||||||
while(i-- > 0){
|
while (i-- > 0)
|
||||||
free_page((long) mm->ldt.u.pages[i]);
|
free_page((long) mm->ldt.u.pages[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
mm->ldt.entry_count = 0;
|
mm->ldt.entry_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,18 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
|
||||||
#include "linux/sched.h"
|
|
||||||
#include "linux/mm.h"
|
#include "linux/mm.h"
|
||||||
#include "asm/elf.h"
|
#include "linux/sched.h"
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "asm/unistd.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "sysdep/sigcontext.h"
|
|
||||||
#include "sysdep/sc.h"
|
|
||||||
|
|
||||||
extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
|
extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
|
||||||
|
|
||||||
@@ -23,7 +16,8 @@ void arch_switch_to(struct task_struct *from, struct task_struct *to)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (err != -EINVAL)
|
if (err != -EINVAL)
|
||||||
printk(KERN_WARNING "arch_switch_tls failed, errno %d, not EINVAL\n", -err);
|
printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
|
||||||
|
"not EINVAL\n", -err);
|
||||||
else
|
else
|
||||||
printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
|
printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
|
||||||
}
|
}
|
||||||
@@ -42,13 +36,13 @@ int is_syscall(unsigned long addr)
|
|||||||
*/
|
*/
|
||||||
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
|
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
|
||||||
if (n != sizeof(instr)) {
|
if (n != sizeof(instr)) {
|
||||||
printk("is_syscall : failed to read instruction from "
|
printk(KERN_ERR "is_syscall : failed to read "
|
||||||
"0x%lx\n", addr);
|
"instruction from 0x%lx\n", addr);
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* int 0x80 or sysenter */
|
/* int 0x80 or sysenter */
|
||||||
return((instr == 0x80cd) || (instr == 0x340f));
|
return (instr == 0x80cd) || (instr == 0x340f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determines which flags the user has access to. */
|
/* determines which flags the user has access to. */
|
||||||
@@ -97,12 +91,12 @@ int poke_user(struct task_struct *child, long addr, long data)
|
|||||||
|
|
||||||
if (addr < MAX_REG_OFFSET)
|
if (addr < MAX_REG_OFFSET)
|
||||||
return putreg(child, addr, data);
|
return putreg(child, addr, data);
|
||||||
|
|
||||||
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
|
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
|
||||||
(addr <= offsetof(struct user, u_debugreg[7]))) {
|
(addr <= offsetof(struct user, u_debugreg[7]))) {
|
||||||
addr -= offsetof(struct user, u_debugreg[0]);
|
addr -= offsetof(struct user, u_debugreg[0]);
|
||||||
addr = addr >> 2;
|
addr = addr >> 2;
|
||||||
if((addr == 4) || (addr == 5)) return -EIO;
|
if ((addr == 4) || (addr == 5))
|
||||||
|
return -EIO;
|
||||||
child->thread.arch.debugregs[addr] = data;
|
child->thread.arch.debugregs[addr] = data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -129,9 +123,9 @@ unsigned long getreg(struct task_struct *child, int regno)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read the word at location addr in the USER area. */
|
||||||
int peek_user(struct task_struct *child, long addr, long data)
|
int peek_user(struct task_struct *child, long addr, long data)
|
||||||
{
|
{
|
||||||
/* read the word at location addr in the USER area. */
|
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
|
|
||||||
if ((addr & 3) || addr < 0)
|
if ((addr & 3) || addr < 0)
|
||||||
@@ -247,8 +241,9 @@ int get_fpregs(unsigned long buf, struct task_struct *child)
|
|||||||
|
|
||||||
err = convert_fxsr_to_user((struct _fpstate __user *) buf,
|
err = convert_fxsr_to_user((struct _fpstate __user *) buf,
|
||||||
&child->thread.regs);
|
&child->thread.regs);
|
||||||
if(err) return(-EFAULT);
|
if (err)
|
||||||
else return(0);
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_fpregs(unsigned long buf, struct task_struct *child)
|
int set_fpregs(unsigned long buf, struct task_struct *child)
|
||||||
@@ -257,8 +252,9 @@ int set_fpregs(unsigned long buf, struct task_struct *child)
|
|||||||
|
|
||||||
err = convert_fxsr_from_user(&child->thread.regs,
|
err = convert_fxsr_from_user(&child->thread.regs,
|
||||||
(struct _fpstate __user *) buf);
|
(struct _fpstate __user *) buf);
|
||||||
if(err) return(-EFAULT);
|
if (err)
|
||||||
else return(0);
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_fpxregs(unsigned long buf, struct task_struct *tsk)
|
int get_fpxregs(unsigned long buf, struct task_struct *tsk)
|
||||||
@@ -284,7 +280,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
|
|||||||
fpu->fos = 0;
|
fpu->fos = 0;
|
||||||
memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)),
|
memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)),
|
||||||
sizeof(fpu->st_space));
|
sizeof(fpu->st_space));
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -292,14 +288,3 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
|
|||||||
{
|
{
|
||||||
return 1;
|
return 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:
|
|
||||||
*/
|
|
||||||
|
@@ -1,17 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/signal.h"
|
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
#include "asm/current.h"
|
|
||||||
#include "asm/ucontext.h"
|
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "asm/unistd.h"
|
#include "asm/unistd.h"
|
||||||
|
#include "asm/uaccess.h"
|
||||||
|
#include "asm/ucontext.h"
|
||||||
#include "frame_kern.h"
|
#include "frame_kern.h"
|
||||||
#include "sigcontext.h"
|
|
||||||
#include "registers.h"
|
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
|
||||||
void copy_sc(struct uml_pt_regs *regs, void *from)
|
void copy_sc(struct uml_pt_regs *regs, void *from)
|
||||||
@@ -52,8 +48,8 @@ static int copy_sc_from_user(struct pt_regs *regs,
|
|||||||
|
|
||||||
err = restore_fp_registers(userspace_pid[0], fpregs);
|
err = restore_fp_registers(userspace_pid[0], fpregs);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
|
printk(KERN_ERR "copy_sc_from_user_skas - PTRACE_SETFPREGS "
|
||||||
"errno = %d\n", -err);
|
"failed, errno = %d\n", -err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +88,8 @@ static int copy_sc_to_user(struct sigcontext __user *to,
|
|||||||
|
|
||||||
err = save_fp_registers(userspace_pid[0], fpregs);
|
err = save_fp_registers(userspace_pid[0], fpregs);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
|
printk(KERN_ERR "copy_sc_to_user_skas - PTRACE_GETFPREGS "
|
||||||
"errno = %d\n", err);
|
"failed, errno = %d\n", err);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
|
to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
|
||||||
@@ -106,8 +102,9 @@ static int copy_sc_to_user(struct sigcontext __user *to,
|
|||||||
copy_to_user(to_fp, fpregs, sizeof(fpregs));
|
copy_to_user(to_fp, fpregs, sizeof(fpregs));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
|
static int copy_ucontext_to_user(struct ucontext __user *uc,
|
||||||
sigset_t *set, unsigned long sp)
|
struct _fpstate __user *fp, sigset_t *set,
|
||||||
|
unsigned long sp)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -300,7 +297,8 @@ long sys_sigreturn(struct pt_regs regs)
|
|||||||
long sys_rt_sigreturn(struct pt_regs regs)
|
long sys_rt_sigreturn(struct pt_regs regs)
|
||||||
{
|
{
|
||||||
unsigned long sp = PT_REGS_SP(¤t->thread.regs);
|
unsigned long sp = PT_REGS_SP(¤t->thread.regs);
|
||||||
struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4);
|
struct rt_sigframe __user *frame =
|
||||||
|
(struct rt_sigframe __user *) (sp - 4);
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
struct ucontext __user *uc = &frame->uc;
|
struct ucontext __user *uc = &frame->uc;
|
||||||
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
|
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
|
||||||
|
@@ -3,19 +3,12 @@
|
|||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/kernel.h"
|
#include "linux/percpu.h"
|
||||||
#include "linux/sched.h"
|
#include "linux/sched.h"
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/segment.h"
|
|
||||||
#include "asm/smp.h"
|
|
||||||
#include "asm/desc.h"
|
|
||||||
#include "kern.h"
|
|
||||||
#include "kern_util.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
#include "sysdep/tls.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If needed we can detect when it's uninitialized.
|
* If needed we can detect when it's uninitialized.
|
||||||
@@ -74,7 +67,8 @@ static inline void clear_user_desc(struct user_desc* info)
|
|||||||
/* Postcondition: LDT_empty(info) returns true. */
|
/* Postcondition: LDT_empty(info) returns true. */
|
||||||
memset(info, 0, sizeof(*info));
|
memset(info, 0, sizeof(*info));
|
||||||
|
|
||||||
/* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
|
/*
|
||||||
|
* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
|
||||||
* indeed an empty user_desc.
|
* indeed an empty user_desc.
|
||||||
*/
|
*/
|
||||||
info->read_exec_only = 1;
|
info->read_exec_only = 1;
|
||||||
@@ -89,10 +83,13 @@ static int load_TLS(int flags, struct task_struct *to)
|
|||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
|
for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
|
||||||
struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
|
struct uml_tls_struct* curr =
|
||||||
|
&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
|
||||||
|
|
||||||
/* Actually, now if it wasn't flushed it gets cleared and
|
/*
|
||||||
* flushed to the host, which will clear it.*/
|
* Actually, now if it wasn't flushed it gets cleared and
|
||||||
|
* flushed to the host, which will clear it.
|
||||||
|
*/
|
||||||
if (!curr->present) {
|
if (!curr->present) {
|
||||||
if (!curr->flushed) {
|
if (!curr->flushed) {
|
||||||
clear_user_desc(&curr->tls);
|
clear_user_desc(&curr->tls);
|
||||||
@@ -116,7 +113,8 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify if we need to do a flush for the new process, i.e. if there are any
|
/*
|
||||||
|
* Verify if we need to do a flush for the new process, i.e. if there are any
|
||||||
* present desc's, only if they haven't been flushed.
|
* present desc's, only if they haven't been flushed.
|
||||||
*/
|
*/
|
||||||
static inline int needs_TLS_update(struct task_struct *task)
|
static inline int needs_TLS_update(struct task_struct *task)
|
||||||
@@ -125,10 +123,13 @@ static inline int needs_TLS_update(struct task_struct *task)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
|
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
|
||||||
struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
|
struct uml_tls_struct* curr =
|
||||||
|
&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
|
||||||
|
|
||||||
/* Can't test curr->present, we may need to clear a descriptor
|
/*
|
||||||
* which had a value. */
|
* Can't test curr->present, we may need to clear a descriptor
|
||||||
|
* which had a value.
|
||||||
|
*/
|
||||||
if (curr->flushed)
|
if (curr->flushed)
|
||||||
continue;
|
continue;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@@ -137,7 +138,8 @@ static inline int needs_TLS_update(struct task_struct *task)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On a newly forked process, the TLS descriptors haven't yet been flushed. So
|
/*
|
||||||
|
* On a newly forked process, the TLS descriptors haven't yet been flushed. So
|
||||||
* we mark them as such and the first switch_to will do the job.
|
* we mark them as such and the first switch_to will do the job.
|
||||||
*/
|
*/
|
||||||
void clear_flushed_tls(struct task_struct *task)
|
void clear_flushed_tls(struct task_struct *task)
|
||||||
@@ -145,10 +147,13 @@ void clear_flushed_tls(struct task_struct *task)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
|
for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
|
||||||
struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
|
struct uml_tls_struct* curr =
|
||||||
|
&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
|
||||||
|
|
||||||
/* Still correct to do this, if it wasn't present on the host it
|
/*
|
||||||
* will remain as flushed as it was. */
|
* Still correct to do this, if it wasn't present on the host it
|
||||||
|
* will remain as flushed as it was.
|
||||||
|
*/
|
||||||
if (!curr->present)
|
if (!curr->present)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -156,23 +161,27 @@ void clear_flushed_tls(struct task_struct *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
|
/*
|
||||||
|
* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
|
||||||
* common host process. So this is needed in SKAS0 too.
|
* common host process. So this is needed in SKAS0 too.
|
||||||
*
|
*
|
||||||
* However, if each thread had a different host process (and this was discussed
|
* However, if each thread had a different host process (and this was discussed
|
||||||
* for SMP support) this won't be needed.
|
* for SMP support) this won't be needed.
|
||||||
*
|
*
|
||||||
* And this will not need be used when (and if) we'll add support to the host
|
* And this will not need be used when (and if) we'll add support to the host
|
||||||
* SKAS patch. */
|
* SKAS patch.
|
||||||
|
*/
|
||||||
|
|
||||||
int arch_switch_tls(struct task_struct *from, struct task_struct *to)
|
int arch_switch_tls(struct task_struct *from, struct task_struct *to)
|
||||||
{
|
{
|
||||||
if (!host_supports_tls)
|
if (!host_supports_tls)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* We have no need whatsoever to switch TLS for kernel threads; beyond
|
/*
|
||||||
|
* We have no need whatsoever to switch TLS for kernel threads; beyond
|
||||||
* that, that would also result in us calling os_set_thread_area with
|
* that, that would also result in us calling os_set_thread_area with
|
||||||
* userspace_pid[cpu] == 0, which gives an error. */
|
* userspace_pid[cpu] == 0, which gives an error.
|
||||||
|
*/
|
||||||
if (likely(to->mm))
|
if (likely(to->mm))
|
||||||
return load_TLS(O_FORCE, to);
|
return load_TLS(O_FORCE, to);
|
||||||
|
|
||||||
@@ -232,17 +241,20 @@ static int get_tls_entry(struct task_struct* task, struct user_desc *info, int i
|
|||||||
*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
|
*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* Temporary debugging check, to make sure that things have been
|
/*
|
||||||
|
* Temporary debugging check, to make sure that things have been
|
||||||
* flushed. This could be triggered if load_TLS() failed.
|
* flushed. This could be triggered if load_TLS() failed.
|
||||||
*/
|
*/
|
||||||
if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
|
if (unlikely(task == current &&
|
||||||
|
!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
|
||||||
printk(KERN_ERR "get_tls_entry: task with pid %d got here "
|
printk(KERN_ERR "get_tls_entry: task with pid %d got here "
|
||||||
"without flushed TLS.", current->pid);
|
"without flushed TLS.", current->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
clear:
|
clear:
|
||||||
/* When the TLS entry has not been set, the values read to user in the
|
/*
|
||||||
|
* When the TLS entry has not been set, the values read to user in the
|
||||||
* tls_array are 0 (because it's cleared at boot, see
|
* tls_array are 0 (because it's cleared at boot, see
|
||||||
* arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
|
* arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
|
||||||
*/
|
*/
|
||||||
@@ -344,8 +356,10 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* XXX: This part is probably common to i386 and x86-64. Don't create a common
|
/*
|
||||||
* file for now, do that when implementing x86-64 support.*/
|
* XXX: This part is probably common to i386 and x86-64. Don't create a common
|
||||||
|
* file for now, do that when implementing x86-64 support.
|
||||||
|
*/
|
||||||
static int __init __setup_host_supports_tls(void)
|
static int __init __setup_host_supports_tls(void)
|
||||||
{
|
{
|
||||||
check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
|
check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
|
||||||
|
@@ -14,6 +14,7 @@ struct exception_table_entry
|
|||||||
};
|
};
|
||||||
|
|
||||||
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
||||||
|
|
||||||
int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
|
int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
|
||||||
{
|
{
|
||||||
const struct exception_table_entry *fixup;
|
const struct exception_table_entry *fixup;
|
||||||
@@ -21,7 +22,7 @@ int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
|
|||||||
fixup = search_exception_tables(address);
|
fixup = search_exception_tables(address);
|
||||||
if (fixup != 0) {
|
if (fixup != 0) {
|
||||||
UPT_IP(regs) = fixup->fixup;
|
UPT_IP(regs) = fixup->fixup;
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -3,16 +3,11 @@
|
|||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/stddef.h"
|
|
||||||
#include "linux/errno.h"
|
|
||||||
#include "linux/personality.h"
|
#include "linux/personality.h"
|
||||||
#include "linux/ptrace.h"
|
#include "linux/ptrace.h"
|
||||||
#include "asm/current.h"
|
#include "asm/unistd.h"
|
||||||
#include "asm/uaccess.h"
|
#include "asm/uaccess.h"
|
||||||
#include "asm/sigcontext.h"
|
#include "asm/ucontext.h"
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/arch/ucontext.h"
|
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "frame_kern.h"
|
#include "frame_kern.h"
|
||||||
#include "skas.h"
|
#include "skas.h"
|
||||||
|
|
||||||
@@ -262,13 +257,3 @@ long sys_rt_sigreturn(struct pt_regs *regs)
|
|||||||
force_sig(SIGSEGV, current);
|
force_sig(SIGSEGV, current);
|
||||||
return 0;
|
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:
|
|
||||||
*/
|
|
||||||
|
@@ -1,30 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Copyright 2003 PathScale, Inc.
|
* Copyright 2003 PathScale, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/linkage.h"
|
#include "linux/linkage.h"
|
||||||
#include "linux/slab.h"
|
|
||||||
#include "linux/shm.h"
|
|
||||||
#include "linux/utsname.h"
|
|
||||||
#include "linux/personality.h"
|
#include "linux/personality.h"
|
||||||
#include "asm/uaccess.h"
|
#include "linux/utsname.h"
|
||||||
#define __FRAME_OFFSETS
|
|
||||||
#include "asm/ptrace.h"
|
|
||||||
#include "asm/unistd.h"
|
|
||||||
#include "asm/prctl.h" /* XXX This should get the constants from libc */
|
#include "asm/prctl.h" /* XXX This should get the constants from libc */
|
||||||
#include "kern.h"
|
#include "asm/uaccess.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
asmlinkage long sys_uname64(struct new_utsname __user * name)
|
asmlinkage long sys_uname64(struct new_utsname __user * name)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
down_read(&uts_sem);
|
down_read(&uts_sem);
|
||||||
err = copy_to_user(name, utsname(), sizeof (*name));
|
err = copy_to_user(name, utsname(), sizeof (*name));
|
||||||
up_read(&uts_sem);
|
up_read(&uts_sem);
|
||||||
|
|
||||||
if (personality(current->personality) == PER_LINUX32)
|
if (personality(current->personality) == PER_LINUX32)
|
||||||
err |= copy_to_user(&name->machine, "i686", 5);
|
err |= copy_to_user(&name->machine, "i686", 5);
|
||||||
|
|
||||||
return err ? -EFAULT : 0;
|
return err ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -55,14 +55,3 @@ extern int init_new_context(struct task_struct *task, struct mm_struct *mm);
|
|||||||
extern void destroy_context(struct mm_struct *mm);
|
extern void destroy_context(struct mm_struct *mm);
|
||||||
|
|
||||||
#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:
|
|
||||||
*/
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -17,11 +17,14 @@ struct task_struct;
|
|||||||
struct mm_struct;
|
struct mm_struct;
|
||||||
|
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
/* This flag is set to 1 before calling do_fork (and analyzed in
|
struct task_struct *saved_task;
|
||||||
|
/*
|
||||||
|
* This flag is set to 1 before calling do_fork (and analyzed in
|
||||||
* copy_thread) to mark that we are begin called from userspace (fork /
|
* copy_thread) to mark that we are begin called from userspace (fork /
|
||||||
* vfork / clone), and reset to 0 after. It is left to 0 when called
|
* vfork / clone), and reset to 0 after. It is left to 0 when called
|
||||||
* from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */
|
* from kernelspace (i.e. kernel_thread() or fork_idle(),
|
||||||
struct task_struct *saved_task;
|
* as of 2.6.11).
|
||||||
|
*/
|
||||||
int forking;
|
int forking;
|
||||||
int nsyscalls;
|
int nsyscalls;
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -9,9 +9,8 @@
|
|||||||
#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
|
#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
|
||||||
|
|
||||||
#include "linux/compiler.h"
|
#include "linux/compiler.h"
|
||||||
#include "sysdep/ptrace.h"
|
|
||||||
#include "asm/ptrace-generic.h"
|
#include "asm/ptrace-generic.h"
|
||||||
#include "asm/host_ldt.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
|
||||||
#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
|
#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
|
||||||
#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
|
#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
|
||||||
@@ -40,6 +39,12 @@
|
|||||||
|
|
||||||
#define user_mode(r) UPT_IS_USER(&(r)->regs)
|
#define user_mode(r) UPT_IS_USER(&(r)->regs)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward declaration to avoid including sysdep/tls.h, which causes a
|
||||||
|
* circular include, and compilation failures.
|
||||||
|
*/
|
||||||
|
struct user_desc;
|
||||||
|
|
||||||
extern int ptrace_get_thread_area(struct task_struct *child, int idx,
|
extern int ptrace_get_thread_area(struct task_struct *child, int idx,
|
||||||
struct user_desc __user *user_desc);
|
struct user_desc __user *user_desc);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user