Commit eaca2b6e authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.8

parent ab249d46
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 7
SUBLEVEL = 8
all: Version zImage
......
......@@ -193,17 +193,11 @@ static void setup_dev(struct gendisk *dev)
blk_size[dev->major] = dev->sizes;
}
/* This may be used only once, enforced by 'static int callable' */
asmlinkage int sys_setup(void * BIOS)
void device_setup(void * BIOS)
{
static int callable = 1;
struct gendisk *p;
int nr=0;
if (!callable)
return -1;
callable = 0;
for (p = gendisk_head ; p ; p=p->next) {
setup_dev(p);
nr += p->nr_real;
......@@ -211,6 +205,4 @@ asmlinkage int sys_setup(void * BIOS)
if (ramdisk_size)
rd_load();
mount_root();
return (0);
}
......@@ -35,27 +35,6 @@
#include <asm/segment.h>
#include <asm/bitops.h>
/*
* Serial driver configuration section. Here are the various options:
*
* CONFIG_AUTO_IRQ
* Enables automatic IRQ detection. I've put in some
* fixes to this which should make this work much more
* cleanly than it used to in 0.98pl2-6. It should be
* much less vulnerable to false IRQs now.
*
* CONFIG_AST_FOURPORT
* Enables support for the AST Fourport serial port.
*
* CONFIG_ACCENT_ASYNC
* Enables support for the Accent Async 4 port serial
* port.
*
* CONFIG_HUB6
* Enables support for the venerable Bell Technologies
* HUB6 card.
*/
#undef ISR_HACK
/*
......
......@@ -460,7 +460,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
((int) SCpnt->request.bh->b_data) + (SCpnt->request.nr_sectors << 9) - 1 >
ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) {
if(((int) SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD)
bounce_buffer = scsi_malloc(bounce_size);
bounce_buffer = (char *) scsi_malloc(bounce_size);
if(!bounce_buffer) contiguous = 0;
};
......@@ -606,7 +606,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
if(!sgpnt[count].alt_address) {count--; continue; }
if(dma_free_sectors > 10)
tmp = scsi_malloc(sgpnt[count].length + bhp->b_size);
tmp = (char *) scsi_malloc(sgpnt[count].length + bhp->b_size);
else {
tmp = NULL;
max_sg = SCpnt->use_sg;
......
......@@ -1767,7 +1767,7 @@ asmlinkage int sync_old_buffers(void)
repeat:
bh = lru_list[nlist];
if(bh)
for (i = nr_buffers_type[nlist]; --i > 0; bh = next) {
for (i = nr_buffers_type[nlist]; i-- > 0; bh = next) {
/* We may have stalled while waiting for I/O to complete. */
if(bh->b_list != nlist) goto repeat;
next = bh->b_next_free;
......@@ -1909,6 +1909,9 @@ asmlinkage int sys_bdflush(int func, int data)
if(nr_buffers_type[BUF_DIRTY] < (nr_buffers - nr_buffers_type[BUF_SHARED]) *
bdf_prm.b_un.nfract/100) {
if (current->signal & (1 << (SIGKILL-1)))
return 0;
current->signal = 0;
interruptible_sleep_on(&bdflush_wait);
}
}
......
......@@ -754,6 +754,17 @@ struct linux_binfmt formats[] = {
{NULL, NULL}
};
static void set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
if (end <= start)
return;
do_mmap(NULL, start, end - start,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, 0);
}
/*
* These are the functions used to load a.out style executables and shared
* libraries. There is no binary dependent code anywhere else.
......@@ -790,7 +801,8 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->end_code = N_TXTADDR(ex) + ex.a_text;
current->end_data = ex.a_data + current->end_code;
current->start_brk = current->brk = current->end_data;
current->start_brk = current->end_data;
current->brk = current->start_brk + ex.a_bss;
current->start_code += N_TXTADDR(ex);
current->rss = 0;
current->suid = current->euid = bprm->e_uid;
......@@ -842,7 +854,7 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->inode->i_count++;
}
beyond_if:
sys_brk(current->brk+ex.a_bss);
set_brk(current->start_brk, current->brk);
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
......
......@@ -8,69 +8,87 @@
#include <linux/config.h>
#include <linux/fs.h>
#ifdef CONFIG_MINIX_FS
#include <linux/minix_fs.h>
#endif
#ifdef CONFIG_XIA_FS
#include <linux/xia_fs.h>
#endif
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#endif
#ifdef CONFIG_EXT2_FS
#include <linux/ext2_fs.h>
#endif
#ifdef CONFIG_EXT_FS
#include <linux/ext_fs.h>
#endif
#ifdef CONFIG_MSDOS_FS
#include <linux/ext2_fs.h>
#include <linux/xia_fs.h>
#include <linux/msdos_fs.h>
#endif
#ifdef CONFIG_NFS_FS
#include <linux/proc_fs.h>
#include <linux/nfs_fs.h>
#endif
#ifdef CONFIG_ISO9660_FS
#include <linux/iso_fs.h>
#endif
#ifdef CONFIG_HPFS_FS
#include <linux/hpfs_fs.h>
#endif
#ifdef CONFIG_SYSV_FS
#include <linux/sysv_fs.h>
#endif
#include <linux/hpfs_fs.h>
extern void device_setup(void);
/* This may be used only once, enforced by 'static int callable' */
asmlinkage int sys_setup(void)
{
static int callable = 1;
if (!callable)
return -1;
callable = 0;
device_setup();
struct file_system_type file_systems[] = {
#ifdef CONFIG_MINIX_FS
{minix_read_super, "minix", 1},
register_filesystem(&(struct file_system_type)
{minix_read_super, "minix", 1, NULL});
#endif
#ifdef CONFIG_EXT_FS
{ext_read_super, "ext", 1},
register_filesystem(&(struct file_system_type)
{ext_read_super, "ext", 1, NULL});
#endif
#ifdef CONFIG_EXT2_FS
{ext2_read_super, "ext2", 1},
register_filesystem(&(struct file_system_type)
{ext2_read_super, "ext2", 1, NULL});
#endif
#ifdef CONFIG_XIA_FS
{xiafs_read_super, "xiafs", 1},
register_filesystem(&(struct file_system_type)
{xiafs_read_super, "xiafs", 1, NULL});
#endif
#ifdef CONFIG_MSDOS_FS
{msdos_read_super, "msdos", 1},
register_filesystem(&(struct file_system_type)
{msdos_read_super, "msdos", 1, NULL});
#endif
#ifdef CONFIG_PROC_FS
{proc_read_super, "proc", 0},
register_filesystem(&(struct file_system_type)
{proc_read_super, "proc", 0, NULL});
#endif
#ifdef CONFIG_NFS_FS
{nfs_read_super, "nfs", 0},
register_filesystem(&(struct file_system_type)
{nfs_read_super, "nfs", 0, NULL});
#endif
#ifdef CONFIG_ISO9660_FS
{isofs_read_super, "iso9660", 1},
register_filesystem(&(struct file_system_type)
{isofs_read_super, "iso9660", 1, NULL});
#endif
#ifdef CONFIG_SYSV_FS
{sysv_read_super, "xenix", 1},
{sysv_read_super, "sysv", 1},
{sysv_read_super, "coherent", 1},
register_filesystem(&(struct file_system_type)
{sysv_read_super, "xenix", 1, NULL});
register_filesystem(&(struct file_system_type)
{sysv_read_super, "sysv", 1, NULL});
register_filesystem(&(struct file_system_type)
{sysv_read_super, "coherent", 1, NULL});
#endif
#ifdef CONFIG_HPFS_FS
{hpfs_read_super, "hpfs", 1},
register_filesystem(&(struct file_system_type)
{hpfs_read_super, "hpfs", 1, NULL});
#endif
{NULL, NULL, 0}
};
mount_root();
return 0;
}
......@@ -419,11 +419,6 @@ struct inode * get_pipe_inode(void)
return inode;
}
struct inode * iget(struct super_block * sb,int nr)
{
return __iget(sb,nr,1);
}
struct inode * __iget(struct super_block * sb, int nr, int crossmntp)
{
static struct wait_queue * update_wait = NULL;
......
......@@ -20,12 +20,6 @@
#include <asm/segment.h>
/*
* The definition of file_systems that used to be here is now in
* filesystems.c. Now super.c contains no fs specific code. -- jrs
*/
extern struct file_system_type file_systems[];
extern struct file_operations * get_blkfops(unsigned int);
extern struct file_operations * get_chrfops(unsigned int);
......@@ -41,16 +35,54 @@ static int do_remount_sb(struct super_block *sb, int flags, char * data);
/* this is initialized in init/main.c */
dev_t ROOT_DEV = 0;
static struct file_system_type * file_systems = NULL;
int register_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
if (!fs)
return -EINVAL;
if (fs->next)
return -EBUSY;
tmp = &file_systems;
while (*tmp) {
if (strcmp((*tmp)->name, fs->name) == 0)
return -EBUSY;
tmp = &(*tmp)->next;
}
*tmp = fs;
return 0;
}
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
return 0;
}
tmp = &(*tmp)->next;
}
return -EINVAL;
}
struct file_system_type *get_fs_type(char *name)
{
int a;
struct file_system_type * fs = file_systems;
if (!name)
return &file_systems[0];
for(a = 0 ; file_systems[a].read_super ; a++)
if (!strcmp(name,file_systems[a].name))
return(&file_systems[a]);
return NULL;
return fs;
while (fs) {
if (!strcmp(name,fs->name))
break;
fs = fs->next;
}
return fs;
}
void __wait_on_super(struct super_block * sb)
......@@ -516,7 +548,7 @@ void mount_root(void)
printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
wait_for_keypress();
}
for (fs_type = file_systems; fs_type->read_super; fs_type++) {
for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!fs_type->requires_dev)
continue;
sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
......
......@@ -52,6 +52,20 @@ __asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
static inline void and_user_long(unsigned long val,int * addr)
{
__asm__ ("andl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
}
#define and_fs_long(x,addr) and_user_long((x),(int *)(addr))
static inline void or_user_long(unsigned long val,int * addr)
{
__asm__ ("orl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
}
#define or_fs_long(x,addr) or_user_long((x),(int *)(addr))
static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n)
{
__asm__("cld\n\t"
......
......@@ -316,10 +316,14 @@ struct file_system_type {
struct super_block *(*read_super) (struct super_block *, void *, int);
char *name;
int requires_dev;
struct file_system_type * next;
};
#ifdef __KERNEL__
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
asmlinkage int sys_open(const char *, int, int);
asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */
......@@ -359,12 +363,11 @@ extern int nr_files;
extern struct super_block super_blocks[NR_SUPER];
extern int shrink_buffers(unsigned int priority);
extern void refile_buffer(struct buffer_head * buf);
void set_writetime(struct buffer_head * buf, int flag);
struct buffer_head ** buffer_pages;
extern void set_writetime(struct buffer_head * buf, int flag);
extern void refill_freelist(int size);
extern struct buffer_head ** buffer_pages;
extern int nr_buffers;
extern int buffermem;
extern int nr_buffer_heads;
......@@ -413,7 +416,6 @@ extern int open_namei(const char * pathname, int flag, int mode,
extern int do_mknod(const char * filename, int mode, dev_t dev);
extern void iput(struct inode * inode);
extern struct inode * __iget(struct super_block * sb,int nr,int crsmnt);
extern struct inode * iget(struct super_block * sb,int nr);
extern struct inode * get_empty_inode(void);
extern void insert_inode_hash(struct inode *);
extern void clear_inode(struct inode *);
......@@ -449,6 +451,11 @@ extern int generic_mmap(struct inode *, struct file *, unsigned long, size_t, in
extern int block_fsync(struct inode *, struct file *);
extern int file_fsync(struct inode *, struct file *);
extern inline struct inode * iget(struct super_block * sb,int nr)
{
return __iget(sb,nr,1);
}
#endif /* __KERNEL__ */
#endif
......@@ -7,6 +7,7 @@
#ifdef __KERNEL__
#include <stdarg.h>
#include <linux/linkage.h>
#define INT_MAX ((int)(~0U>>1))
......@@ -40,14 +41,15 @@ NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2)));
NORET_TYPE void do_exit(long error_code)
ATTRIB_NORET;
unsigned long simple_strtoul(const char *,char **,unsigned int);
int sprintf(char * buf, const char * fmt, ...);
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern int sprintf(char * buf, const char * fmt, ...);
extern int vsprintf(char *buf, const char *, va_list);
int session_of_pgrp(int pgrp);
extern int session_of_pgrp(int pgrp);
int kill_proc(int pid, int sig, int priv);
int kill_pg(int pgrp, int sig, int priv);
int kill_sl(int sess, int sig, int priv);
extern int kill_proc(int pid, int sig, int priv);
extern int kill_pg(int pgrp, int sig, int priv);
extern int kill_sl(int sess, int sig, int priv);
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
......
......@@ -47,23 +47,23 @@
stack during a system call. */
struct pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
unsigned short ds, __dsu;
unsigned short es, __esu;
unsigned short fs, __fsu;
unsigned short gs, __gsu;
long orig_eax;
long eip;
unsigned short cs, __csu;
long eflags;
long esp;
unsigned short ss, __ssu;
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
unsigned short ds, __dsu;
unsigned short es, __esu;
unsigned short fs, __fsu;
unsigned short gs, __gsu;
long orig_eax;
long eip;
unsigned short cs, __csu;
long eflags;
long esp;
unsigned short ss, __ssu;
};
#endif
......@@ -492,6 +492,9 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table *
extern void __down(struct semaphore * sem);
/*
* These are not yet interrupt-safe
*/
extern inline void down(struct semaphore * sem)
{
if (sem->count <= 0)
......
......@@ -89,4 +89,33 @@ struct sigaction {
void (*sa_restorer)(void);
};
#ifdef __KERNEL__
struct sigcontext_struct {
unsigned short gs, __gsh;
unsigned short fs, __fsh;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long esp;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
unsigned long trapno;
unsigned long err;
unsigned long eip;
unsigned short cs, __csh;
unsigned long eflags;
unsigned long esp_at_signal;
unsigned short ss, __ssh;
unsigned long i387;
unsigned long oldmask;
unsigned long cr2;
};
#endif
#endif
#ifndef _LINUX_VM86_H
#define _LINUX_VM86_H
#define VM_MASK 0x00020000
#define TF_MASK 0x00000100
#define IF_MASK 0x00000200
#define IOPL_MASK 0x00003000
#define NT_MASK 0x00004000
#define VM_MASK 0x00020000
#define AC_MASK 0x00040000
#define BIOSSEG 0x0f000
#define CPU_286 2
#define CPU_386 3
#define CPU_486 4
/*
* This is the stack-layout when we have done a "SAVE_ALL" from vm86
......@@ -29,23 +40,28 @@ struct vm86_regs {
long __null_gs;
long orig_eax;
long eip;
long cs;
unsigned short cs, __csh;
long eflags;
long esp;
long ss;
unsigned short ss, __ssh;
/*
* these are specific to v86 mode:
*/
long es;
long ds;
long fs;
long gs;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned short fs, __fsh;
unsigned short gs, __gsh;
};
struct vm86_struct {
struct vm86_regs regs;
unsigned long flags;
unsigned long screen_bitmap;
unsigned long v_eflags;
unsigned long cpu_type;
unsigned long return_if_iflag;
unsigned char int_revectored[0x100];
unsigned char int21_revectored[0x100];
};
/*
......@@ -53,4 +69,10 @@ struct vm86_struct {
*/
#define VM86_SCREEN_BITMAP 1
#ifdef __KERNEL__
void handle_vm86_fault(struct vm86_regs *, long);
#endif
#endif
......@@ -47,7 +47,7 @@ struct desc_struct default_ldt;
static inline _syscall0(int,idle)
static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
static inline _syscall0(int,setup)
static inline _syscall0(int,sync)
static inline _syscall0(pid_t,setsid)
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
......@@ -488,7 +488,7 @@ void init(void)
{
int pid,i;
setup((void *) &drive_info);
setup();
sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
(void) open("/dev/tty1",O_RDWR,0);
(void) dup(0);
......
......@@ -19,7 +19,7 @@
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \
panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \
signal.o mktime.o ptrace.o ioport.o itimer.o \
info.o ldt.o time.o
info.o ldt.o time.o vm86.o
all: kernel.o
......
......@@ -8,6 +8,8 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#define X(name) { (void *) &name, "_" #name }
......@@ -20,26 +22,56 @@ struct {
void *addr;
const char *name;
} symbol_table[] = {
/* process memory management */
X(wp_works_ok),
X(__verify_write),
X(do_mmap),
X(do_munmap),
/* internal kernel memory management */
X(__get_free_pages),
X(free_pages),
X(kmalloc),
X(kfree_s),
X(vmalloc),
X(vfree),
/* filesystem internal functions */
X(getname),
X(putname),
X(__iget),
X(iput),
X(namei),
X(lnamei),
/* device registration */
X(register_chrdev),
X(unregister_chrdev),
X(register_blkdev),
X(unregister_blkdev),
X(wake_up_interruptible),
X(wp_works_ok),
X(__verify_write),
/* interrupt handling */
X(request_irq),
X(free_irq),
/* process management */
X(wake_up),
X(wake_up_interruptible),
X(schedule),
X(current),
X(jiffies),
X(xtime),
/* misc */
X(printk),
X(schedule),
X(sprintf),
X(vsprintf),
#ifdef CONFIG_FTAPE
/* The next labels are needed for ftape driver. */
X(ftape_big_buffer),
X(do_floppy),
#endif
};
int symbol_table_size = sizeof (symbol_table) / sizeof (symbol_table[0]);
......@@ -22,31 +22,6 @@ extern int core_dump(long signr,struct pt_regs * regs);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
struct sigcontext_struct {
unsigned short gs, __gsh;
unsigned short fs, __fsh;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long esp;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
unsigned long trapno;
unsigned long err;
unsigned long eip;
unsigned short cs, __csh;
unsigned long eflags;
unsigned long esp_at_signal;
unsigned short ss, __ssh;
unsigned long i387;
unsigned long oldmask;
unsigned long cr2;
};
asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
{
sigset_t new_set, old_set = current->blocked;
......
......@@ -131,84 +131,6 @@ asmlinkage int sys_prof(void)
return -ENOSYS;
}
asmlinkage unsigned long save_v86_state(struct vm86_regs * regs)
{
unsigned long stack;
if (!current->vm86_info) {
printk("no vm86_info: BAD\n");
do_exit(SIGSEGV);
}
memcpy_tofs(&(current->vm86_info->regs),regs,sizeof(*regs));
put_fs_long(current->screen_bitmap,&(current->vm86_info->screen_bitmap));
stack = current->tss.esp0;
current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0;
return stack;
}
static void mark_screen_rdonly(struct task_struct * tsk)
{
unsigned long tmp;
unsigned long *pg_table;
if ((tmp = tsk->tss.cr3) != 0) {
tmp = *(unsigned long *) tmp;
if (tmp & PAGE_PRESENT) {
tmp &= PAGE_MASK;
pg_table = (0xA0000 >> PAGE_SHIFT) + (unsigned long *) tmp;
tmp = 32;
while (tmp--) {
if (PAGE_PRESENT & *pg_table)
*pg_table &= ~PAGE_RW;
pg_table++;
}
}
}
}
asmlinkage int sys_vm86(struct vm86_struct * v86)
{
struct vm86_struct info;
struct pt_regs * pt_regs = (struct pt_regs *) &v86;
int error;
if (current->saved_kernel_stack)
return -EPERM;
/* v86 must be readable (now) and writable (for save_v86_state) */
error = verify_area(VERIFY_WRITE,v86,sizeof(*v86));
if (error)
return error;
memcpy_fromfs(&info,v86,sizeof(info));
/*
* make sure the vm86() system call doesn't try to do anything silly
*/
info.regs.__null_ds = 0;
info.regs.__null_es = 0;
info.regs.__null_fs = 0;
info.regs.__null_gs = 0;
/*
* The eflags register is also special: we cannot trust that the user
* has set it up safely, so this makes sure interrupt etc flags are
* inherited from protected mode.
*/
info.regs.eflags &= 0x00000dd5;
info.regs.eflags |= ~0x00000dd5 & pt_regs->eflags;
info.regs.eflags |= VM_MASK;
current->saved_kernel_stack = current->tss.esp0;
current->tss.esp0 = (unsigned long) pt_regs;
current->vm86_info = v86;
current->screen_bitmap = info.screen_bitmap;
if (info.flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(current);
__asm__ __volatile__("movl %0,%%esp\n\t"
"pushl $ret_from_sys_call\n\t"
"ret"
: /* no outputs */
:"g" ((long) &(info.regs)),"a" (info.regs.eax));
return 0;
}
extern void hard_reset_now(void);
/*
......
......@@ -125,10 +125,21 @@ DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
DO_ERROR(11, SIGSEGV, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGSEGV, "stack segment", stack_segment, current)
DO_ERROR(13, SIGSEGV, "general protection", general_protection, current)
DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct vm86_regs *) regs, error_code);
return;
}
current->tss.error_code = error_code;
current->tss.trap_no = 13;
send_sig(SIGSEGV, current, 1);
die_if_kernel("general protection",regs,error_code);
}
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{
printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
......
/*
* linux/kernel/vm86.c
*
* Copyright (C) 1994 Linus Torvalds
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <asm/segment.h>
#include <asm/io.h>
asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
{
unsigned long stack;
if (!current->vm86_info) {
printk("no vm86_info: BAD\n");
do_exit(SIGSEGV);
}
memcpy_tofs(&(current->vm86_info->regs),regs,sizeof(*regs));
put_fs_long(current->screen_bitmap,&(current->vm86_info->screen_bitmap));
stack = current->tss.esp0;
current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0;
return (struct pt_regs *) stack;
}
static void mark_screen_rdonly(struct task_struct * tsk)
{
unsigned long tmp;
unsigned long *pg_table;
if ((tmp = tsk->tss.cr3) != 0) {
tmp = *(unsigned long *) tmp;
if (tmp & PAGE_PRESENT) {
tmp &= PAGE_MASK;
pg_table = (0xA0000 >> PAGE_SHIFT) + (unsigned long *) tmp;
tmp = 32;
while (tmp--) {
if (PAGE_PRESENT & *pg_table)
*pg_table &= ~PAGE_RW;
pg_table++;
}
}
}
}
asmlinkage int sys_vm86(struct vm86_struct * v86)
{
struct vm86_struct info;
struct pt_regs * pt_regs = (struct pt_regs *) &v86;
int error;
if (current->saved_kernel_stack)
return -EPERM;
/* v86 must be readable (now) and writable (for save_v86_state) */
error = verify_area(VERIFY_WRITE,v86,sizeof(*v86));
if (error)
return error;
memcpy_fromfs(&info,v86,sizeof(info));
/*
* make sure the vm86() system call doesn't try to do anything silly
*/
info.regs.__null_ds = 0;
info.regs.__null_es = 0;
info.regs.__null_fs = 0;
info.regs.__null_gs = 0;
/*
* The eflags register is also special: we cannot trust that the user
* has set it up safely, so this makes sure interrupt etc flags are
* inherited from protected mode.
*/
info.regs.eflags &= 0x00000dd5;
info.regs.eflags |= ~0x00000dd5 & pt_regs->eflags;
info.regs.eflags |= VM_MASK;
current->saved_kernel_stack = current->tss.esp0;
current->tss.esp0 = (unsigned long) pt_regs;
current->vm86_info = v86;
current->screen_bitmap = info.screen_bitmap;
if (info.flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(current);
__asm__ __volatile__("movl %0,%%esp\n\t"
"pushl $ret_from_sys_call\n\t"
"ret"
: /* no outputs */
:"g" ((long) &(info.regs)),"a" (info.regs.eax));
return 0;
}
static inline void return_to_32bit(struct vm86_regs * regs16, int retval)
{
struct pt_regs * regs32;
regs32 = save_v86_state(regs16);
regs32->eax = retval;
__asm__("movl %0,%%esp\n\t"
"jmp ret_from_sys_call"
: : "r" (regs32));
}
void handle_vm86_fault(struct vm86_regs * regs, long error_code)
{
unsigned char *csp;
unsigned short *ssp;
unsigned short flags;
unsigned char i;
csp = (unsigned char *) ((regs->cs << 4) + (regs->eip & 0xffff));
ssp = (unsigned short *) ((regs->ss << 4) + (regs->esp & 0xffff));
switch (get_fs_byte(csp)) {
/* operand size override */
case 0x66:
switch (get_fs_byte(++csp)) {
/* pushfd */
case 0x9c:
regs->esp -= 4;
regs->eip += 2;
if (get_fs_long(&(current->vm86_info->cpu_type)) == CPU_386)
put_fs_long(((regs->eflags) & ~(AC_MASK|NT_MASK|IOPL_MASK|IF_MASK)) |
(get_fs_long(&(current->vm86_info->v_eflags)) & (NT_MASK|IOPL_MASK|IF_MASK)), ssp-2);
else
put_fs_long(((regs->eflags) & ~(AC_MASK|NT_MASK|IOPL_MASK|IF_MASK)) |
(get_fs_long(&(current->vm86_info->v_eflags)) & (AC_MASK|NT_MASK|IOPL_MASK|IF_MASK)), ssp-2);
return;
/* popfd */
case 0x9d:
regs->esp += 4;
regs->eip += 2;
flags = get_fs_word(ssp+1);
put_fs_word(flags, (unsigned short *) &(current->vm86_info->v_eflags) +1);
goto return_from_popf;
}
/* pushf */
case 0x9c:
regs->esp -= 2;
regs->eip++;
if (get_fs_long(&(current->vm86_info->cpu_type)) == CPU_286)
put_fs_word(((regs->eflags) & 0x0dd5) |
(get_fs_word(&(current->vm86_info->v_eflags)) & ~0xfdd5), --ssp);
else
put_fs_word(((regs->eflags) & ~(NT_MASK|IOPL_MASK|IF_MASK)) |
(get_fs_word(&(current->vm86_info->v_eflags)) & (NT_MASK|IOPL_MASK|IF_MASK)), --ssp);
return;
/* popf */
case 0x9d:
regs->esp += 2;
regs->eip++;
return_from_popf:
flags = get_fs_word(ssp);
regs->eflags &= ~0x00000dd5;
regs->eflags |= flags & 0x00000dd5;
put_fs_word(flags, &(current->vm86_info->v_eflags));
goto do_dosemu_timer;
/* int 3 */
case 0xcc:
if (get_fs_word((void *)14) == BIOSSEG || regs->cs == BIOSSEG
|| get_fs_byte(&(current->vm86_info->int_revectored[3])))
return_to_32bit(regs, SIGSEGV);
i = 3;
regs->eip++;
goto return_from_int_xx;
/* int xx */
case 0xcd:
i = get_fs_byte(++csp);
if (get_fs_word((void *)((i<<2)+2)) == BIOSSEG
|| regs->cs == BIOSSEG
|| get_fs_byte(&(current->vm86_info->int_revectored[i])))
return_to_32bit(regs, SIGSEGV);
if ((i==0x21) && get_fs_byte(&(current->vm86_info->int21_revectored[((regs->eax >> 4) & 0xff)])))
return_to_32bit(regs, SIGSEGV);
regs->eip+=2;
return_from_int_xx:
regs->esp -= 6;
if (get_fs_long(&(current->vm86_info->cpu_type)) == CPU_286)
put_fs_word(((regs->eflags) & 0x0dd5) |
(get_fs_word(&(current->vm86_info->v_eflags)) & ~0xfdd5), --ssp);
else
put_fs_word(((regs->eflags) & ~IF_MASK) |
(get_fs_word(&(current->vm86_info->v_eflags)) & IF_MASK), --ssp);
put_fs_word(regs->cs, --ssp);
put_fs_word((unsigned short)(regs->eip), --ssp);
regs->cs = get_fs_word((void *)((i<<2)+2));
regs->eip = (unsigned long) get_fs_word((void *)(i<<2));
regs->eflags &= ~TF_MASK;
and_fs_long(~IF_MASK, &(current->vm86_info->v_eflags));
return;
/* iret */
case 0xcf:
regs->esp += 6;
regs->eip = get_fs_word(ssp++);
regs->cs = get_fs_word(ssp++);
goto return_from_popf;
/* cli */
case 0xfa:
regs->eip++;
and_fs_long(~IF_MASK, &(current->vm86_info->v_eflags));
return;
/* sti */
case 0xfb:
regs->eip++;
or_fs_long(IF_MASK, &(current->vm86_info->v_eflags));
do_dosemu_timer:
if ((get_fs_long(&(current->vm86_info->v_eflags)) & IF_MASK) &&
get_fs_long(&(current->vm86_info->return_if_iflag)))
break;
return;
default:
return_to_32bit(regs, SIGSEGV);
}
return_to_32bit(regs, SIGALRM);
}
......@@ -4,25 +4,8 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#ifndef __GNUC__
#error I want gcc!
#endif
#include <linux/types.h>
#ifdef __cplusplus
#define C_BEGIN extern "C" {
#define C_END }
#else
#define C_BEGIN
#define C_END
#endif
#include <linux/string.h>
#undef __cplusplus
#define extern
#define inline
#define __LIBRARY__
/* all the actual functions should be inline anyway, so.. */
C_BEGIN
#include <linux/string.h>
C_END
char * ___strtok = NULL;
......@@ -596,7 +596,7 @@ do { unsigned long size = PAGE_SIZE << high; \
add_mem_queue(free_area_list+high, addr); \
mark_used((unsigned long) addr, high); \
restore_flags(flags); \
addr = (void *) (size + (unsigned long) addr); \
addr = (struct mem_list *) (size + (unsigned long) addr); \
} mem_map[MAP_NR((unsigned long) addr)] = 1; \
} while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment