VERSION = 1
PATCHLEVEL = 1
-SUBLEVEL = 7
+SUBLEVEL = 8
all: Version zImage
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;
if (ramdisk_size)
rd_load();
- mount_root();
- return (0);
}
#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
/*
((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;
};
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;
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;
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);
}
}
{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.
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;
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;
#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;
+}
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;
#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);
/* 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)
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);
#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"
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 */
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;
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 *);
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
#ifdef __KERNEL__
+#include <stdarg.h>
#include <linux/linkage.h>
#define INT_MAX ((int)(~0U>>1))
__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)));
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
extern void __down(struct semaphore * sem);
+/*
+ * These are not yet interrupt-safe
+ */
extern inline void down(struct semaphore * sem)
{
if (sem->count <= 0)
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
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];
};
/*
*/
#define VM86_SCREEN_BITMAP 1
+#ifdef __KERNEL__
+
+void handle_vm86_fault(struct vm86_regs *, long);
+
+#endif
+
#endif
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)
{
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);
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
#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 }
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]);
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;
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);
/*
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");
--- /dev/null
+/*
+ * 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);
+}
* 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;
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)