diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/ChangeLog | 14 | ||||
-rw-r--r-- | kernel/sysctl/patch-2.2.1 | 81 | ||||
-rw-r--r-- | kernel/table.h | 188 | ||||
-rw-r--r-- | kernel/table20/Makefile | 13 | ||||
-rw-r--r-- | kernel/table20/README | 21 | ||||
-rw-r--r-- | kernel/table20/entry-i386.S | 706 | ||||
-rw-r--r-- | kernel/table20/kernel.patch | 51 | ||||
-rw-r--r-- | kernel/table20/main.c | 468 | ||||
-rw-r--r-- | kernel/table20/unistd-i386.h | 324 | ||||
-rw-r--r-- | kernel/table20/version.h | 1 | ||||
-rw-r--r-- | kernel/table21/.cvsignore | 4 | ||||
-rw-r--r-- | kernel/table21/Makefile | 16 | ||||
-rw-r--r-- | kernel/table21/README | 21 | ||||
-rw-r--r-- | kernel/table21/entry-i386.S | 571 | ||||
-rw-r--r-- | kernel/table21/main.c | 61 | ||||
-rw-r--r-- | kernel/table21/module.c | 607 | ||||
-rw-r--r-- | kernel/table21/unistd-i386.h | 344 | ||||
-rw-r--r-- | kernel/table21/version.h | 1 | ||||
-rw-r--r-- | kernel/version.h | 1 |
19 files changed, 3493 insertions, 0 deletions
diff --git a/kernel/ChangeLog b/kernel/ChangeLog new file mode 100644 index 00000000..a3efd8d7 --- /dev/null +++ b/kernel/ChangeLog @@ -0,0 +1,14 @@ +1998-07-21 Martin Baulig <martin@home-of-linux.org> + + * table20: New directory for 2.0.xx kernels. + + * table21: New directory for 2.1.xx kernels. + + * *: Moved into `table20' and `table21'. + +1998-06-14 Martin Baulig <baulig@taurus.uni-trier.de> + + * README: Added README. + + * kernel.patch: Patch for the Linux kernel to add the + new system call. diff --git a/kernel/sysctl/patch-2.2.1 b/kernel/sysctl/patch-2.2.1 new file mode 100644 index 00000000..1781b921 --- /dev/null +++ b/kernel/sysctl/patch-2.2.1 @@ -0,0 +1,81 @@ +diff -ru linux-2.2.1/Makefile hacker/Makefile +--- linux-2.2.1/Makefile Sun Jan 31 22:45:42 1999 ++++ hacker/Makefile Sun Mar 21 16:10:41 1999 +@@ -109,6 +109,7 @@ + DRIVERS =drivers/block/block.a \ + drivers/char/char.a \ + drivers/misc/misc.a ++EXTRAS = + LIBS =$(TOPDIR)/lib/lib.a + SUBDIRS =kernel drivers mm fs net ipc lib + +@@ -186,6 +187,11 @@ + DRIVERS := $(DRIVERS) drivers/net/irda/irda_drivers.a + endif + ++ifdef CONFIG_LIBGTOP ++SUBDIRS := $(SUBDIRS) libgtop ++EXTRAS := $(EXTRAS) libgtop/kernel.o ++endif ++ + include arch/$(ARCH)/Makefile + + .S.s: +@@ -206,6 +212,7 @@ + $(FILESYSTEMS) \ + $(NETWORKS) \ + $(DRIVERS) \ ++ $(EXTRAS) \ + $(LIBS) \ + --end-group \ + -o vmlinux +diff -ru linux-2.2.1/arch/i386/config.in hacker/arch/i386/config.in +--- linux-2.2.1/arch/i386/config.in Sun Jan 31 22:25:25 1999 ++++ hacker/arch/i386/config.in Sat Mar 20 18:26:18 1999 +@@ -84,6 +84,9 @@ + bool 'System V IPC' CONFIG_SYSVIPC + bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT + bool 'Sysctl support' CONFIG_SYSCTL ++if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then ++ tristate 'LibGTop support' CONFIG_LIBGTOP ++fi + tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT + tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF + tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +diff -ru linux-2.2.1/include/linux/sysctl.h hacker/include/linux/sysctl.h +--- linux-2.2.1/include/linux/sysctl.h Sun Jan 31 22:24:14 1999 ++++ hacker/include/linux/sysctl.h Sat Mar 20 19:12:54 1999 +@@ -56,7 +56,8 @@ + CTL_PROC=4, /* Process info */ + CTL_FS=5, /* Filesystems */ + CTL_DEBUG=6, /* Debugging */ +- CTL_DEV=7 /* Devices */ ++ CTL_DEV=7, /* Devices */ ++ CTL_LIBGTOP=408 /* LibGTop */ + }; + + +diff -ru linux-2.2.1/kernel/sysctl.c hacker/kernel/sysctl.c +--- linux-2.2.1/kernel/sysctl.c Sun Jan 31 22:24:43 1999 ++++ hacker/kernel/sysctl.c Sat Mar 20 19:24:34 1999 +@@ -82,7 +82,9 @@ + static ctl_table fs_table[]; + static ctl_table debug_table[]; + static ctl_table dev_table[]; +- ++#ifdef CONFIG_LIBGTOP ++extern ctl_table libgtop_table[]; ++#endif + + /* /proc declarations: */ + +@@ -148,6 +150,9 @@ + {CTL_FS, "fs", NULL, 0, 0555, fs_table}, + {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table}, + {CTL_DEV, "dev", NULL, 0, 0555, dev_table}, ++#ifdef CONFIG_LIBGTOP ++ {CTL_LIBGTOP, "libgtop", NULL, 0, 0555, libgtop_table}, ++#endif + {0} + }; + diff --git a/kernel/table.h b/kernel/table.h new file mode 100644 index 00000000..d4959370 --- /dev/null +++ b/kernel/table.h @@ -0,0 +1,188 @@ +#ifndef _LINUX_TABLE_H +#define _LINUX_TABLE_H + +#ifdef _KERNEL +#include <linux/types.h> +#else +#define NR_TASKS 512 +#endif + +#define TABLE_KERN_PROC_ALL 0 /* all processes */ +#define TABLE_KERN_PROC_PID 1 +#define TABLE_KERN_PROC_PGRP 2 +#define TABLE_KERN_PROC_SESSION 3 +#define TABLE_KERN_PROC_TTY 4 +#define TABLE_KERN_PROC_UID 5 +#define TABLE_KERN_PROC_RUID 6 + +#define TABLE_KERN_PROC_MASK 15 + +#define TABLE_EXCLUDE_IDLE 0x1000 +#define TABLE_EXCLUDE_SYSTEM 0x2000 +#define TABLE_EXCLUDE_NOTTY 0x4000 + +#define TABLE_VERSION 0 +#define TABLE_CPU 1 +#define TABLE_MEM 2 +#define TABLE_SWAP 3 +#define TABLE_LOADAVG 4 +#define TABLE_UPTIME 5 +#define TABLE_PROCLIST 6 +#define TABLE_PROC_UID 7 +#define TABLE_PROC_MEM 8 +#define TABLE_PROC_SEGMENT 9 +#define TABLE_PROC_TIME 10 +#define TABLE_PROC_STATE 11 +#define TABLE_PROC_SIGNAL 12 +#define TABLE_PROC_KERNEL 13 + +/* CPU Usage (in jiffies = 1/100th seconds) */ + +struct table_cpu +{ + unsigned long total; /* Total CPU Time */ + unsigned long user; /* CPU Time in User Mode */ + unsigned long nice; /* CPU Time in User Mode (nice) */ + unsigned long sys; /* CPU Time in System Mode */ + unsigned long idle; /* CPU Time in the Idle Task */ + unsigned long frequency; /* Tick frequency */ +}; + +/* Memory Usage (in bytes) */ + +struct table_mem +{ + unsigned long total; /* Total physical memory */ + unsigned long used; /* Used memory size */ + unsigned long free; /* Free memory size */ + unsigned long shared; /* Shared memory size */ + unsigned long buffer; /* Size of buffers */ + unsigned long cached; /* Size of cached memory */ +}; + +/* Swap Space (in bytes) */ + +struct table_swap +{ + unsigned long total; /* Total swap space */ + unsigned long used; /* Used swap space */ + unsigned long free; /* Free swap space */ + unsigned long pagein; /* Total # of pages swapped in */ + unsigned long pageout; /* Total # of pages swapped out */ +}; + +/* Load average */ + +struct table_loadavg +{ + double loadavg [3]; + unsigned nr_running; + unsigned nr_tasks; + unsigned last_pid; +}; + +/* Uptime */ + +struct table_uptime +{ + unsigned long uptime; + unsigned long idle; +}; + +/* Process list. */ + +struct proclist_args +{ + int which, arg; +}; + +struct table_proclist +{ + int nr_running, nr_tasks, last_pid; + unsigned pids [NR_TASKS]; +}; + +/* Information about processes. */ + +struct table_proc_state +{ + long state; + unsigned long flags; + char comm[16]; + int uid, gid; +}; + +struct table_proc_uid +{ + int uid, euid, suid, fsuid; + int gid, egid, sgid, fsgid; + int pid, pgrp, ppid; + int session; + unsigned int tty; + int tpgid; + long priority; + long counter; + long def_priority; +}; + +struct table_proc_mem +{ + unsigned long context; + unsigned long start_code, end_code, start_data, end_data; + unsigned long start_brk, brk, start_stack, start_mmap; + unsigned long arg_start, arg_end, env_start, env_end; + unsigned long rss, rlim, total_vm, locked_vm; +}; + +struct table_proc_segment +{ + unsigned long vsize; + unsigned long size, resident, shared; + unsigned long trs, lrs, drs, srs, dt; +}; + +struct table_proc_time +{ + long utime, stime, cutime, cstime, start_time; + unsigned long timeout, policy, rt_priority; + unsigned long it_real_value, it_prof_value, it_virt_value; + unsigned long it_real_incr, it_prof_incr, it_virt_incr; +}; + +struct table_proc_signal +{ + unsigned long long signal, + blocked, /* bitmap of masked signals */ + ignored, /* mask of ignored signals */ + caught; /* mask of caught signals */ +}; + +struct table_proc_kernel +{ + unsigned long keip, kesp, wchan; + unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; + unsigned long nswap, cnswap; +}; + +/* Union */ + +union table +{ + struct table_cpu cpu; + struct table_mem mem; + struct table_swap swap; + struct table_loadavg loadavg; + struct table_uptime uptime; + struct table_proclist proclist; + struct table_proc_uid proc_uid; + struct table_proc_mem proc_mem; + struct table_proc_segment proc_segment; + struct table_proc_time proc_time; + struct table_proc_state proc_state; + struct table_proc_signal proc_signal; + struct table_proc_kernel proc_kernel; +}; + +#endif /* _LINUX_IPC_H */ + + diff --git a/kernel/table20/Makefile b/kernel/table20/Makefile new file mode 100644 index 00000000..d24e3ba8 --- /dev/null +++ b/kernel/table20/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for the linux system information tables. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := table.o +O_OBJS := main.o + +include $(TOPDIR)/Rules.make diff --git a/kernel/table20/README b/kernel/table20/README new file mode 100644 index 00000000..88d26bec --- /dev/null +++ b/kernel/table20/README @@ -0,0 +1,21 @@ +This is a new system call `table ()' for the Linux table. It is faster +than reading from /proc and can be used to fetch all information required +for libgtop until whe have some other function (extended sysctl, ...) in +standard kernels. + +I didn't want to change sysctl or some other function myself cause this may +cause other applications relying upon those function to fail. This is +something for the ``real'' kernel gurus ... + +To use this new system call for libgtop, do the following: + +* Copy this directory to /usr/src/linux/table +* Make /usr/src/linux/include/linux/table.h symlink to /usr/src/linux/table/table.h +* Apply the patch `kernel.patch' to the kernel, compile, install and reboot +* Recompile libgtop (remove `config.cache' and run the `autogen.sh' again). + +If you want to change and/or add something - feel free to do so ! + +Have fun, + +Martin diff --git a/kernel/table20/entry-i386.S b/kernel/table20/entry-i386.S new file mode 100644 index 00000000..994fe27c --- /dev/null +++ b/kernel/table20/entry-i386.S @@ -0,0 +1,706 @@ +/* + * linux/arch/i386/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * I changed all the .align's to 4 (16 byte alignment), as that's faster + * on a 486. + * + * Stack layout in 'ret_from_system_call': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in fork.c:copy_process, signal.c:do_signal, + * ptrace.c and ptrace.h + * + * 0(%esp) - %ebx + * 4(%esp) - %ecx + * 8(%esp) - %edx + * C(%esp) - %esi + * 10(%esp) - %edi + * 14(%esp) - %ebp + * 18(%esp) - %eax + * 1C(%esp) - %ds + * 20(%esp) - %es + * 24(%esp) - %fs + * 28(%esp) - %gs + * 2C(%esp) - orig_eax + * 30(%esp) - %eip + * 34(%esp) - %cs + * 38(%esp) - %eflags + * 3C(%esp) - %oldesp + * 40(%esp) - %oldss + */ + +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/segment.h> +#define ASSEMBLY +#include <asm/smp.h> + +EBX = 0x00 +ECX = 0x04 +EDX = 0x08 +ESI = 0x0C +EDI = 0x10 +EBP = 0x14 +EAX = 0x18 +DS = 0x1C +ES = 0x20 +FS = 0x24 +GS = 0x28 +ORIG_EAX = 0x2C +EIP = 0x30 +CS = 0x34 +EFLAGS = 0x38 +OLDESP = 0x3C +OLDSS = 0x40 + +CF_MASK = 0x00000001 +IF_MASK = 0x00000200 +NT_MASK = 0x00004000 +VM_MASK = 0x00020000 + +/* + * these are offsets into the task-struct. + */ +state = 0 +counter = 4 +priority = 8 +signal = 12 +blocked = 16 +flags = 20 +dbgreg6 = 52 +dbgreg7 = 56 +exec_domain = 60 + +ENOSYS = 38 + +#define SAVE_ALL \ + cld; \ + push %gs; \ + push %fs; \ + push %es; \ + push %ds; \ + pushl %eax; \ + pushl %ebp; \ + pushl %edi; \ + pushl %esi; \ + pushl %edx; \ + pushl %ecx; \ + pushl %ebx; \ + movl $(KERNEL_DS),%edx; \ + mov %dx,%ds; \ + mov %dx,%es; \ + movl $(USER_DS),%edx; \ + mov %dx,%fs; + +#ifdef __SMP__ + +#define GET_PROCESSOR_ID \ + movl SYMBOL_NAME(apic_reg), %edx; \ + movl 32(%edx), %eax;\ + movl %eax,SYMBOL_NAME(apic_retval); \ + shrl $24,%eax; \ + andb $0x0F,%al; + +/* + * Get the processor ID multiplied by 4 + */ + +#define GET_PROCESSOR_OFFSET(x) \ + movl SYMBOL_NAME(apic_reg), x ; \ + movl 32( x ), x ; \ + shrl $22, x ; \ + andl $0x3C, x ; + +/* macro LEAVE_KERNEL decrements kernel_counter and resets kernel_flag and + saves processor variables if zero */ +#define LEAVE_KERNEL \ + pushfl; \ + cli; \ + GET_PROCESSOR_ID \ + btrl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \ + decl SYMBOL_NAME(syscall_count); \ + decl SYMBOL_NAME(kernel_counter); \ + jnz 1f; \ + movb SYMBOL_NAME(saved_active_kernel_processor), %al; \ + movb %al, SYMBOL_NAME(active_kernel_processor); \ + cmpb $(NO_PROC_ID), %al; \ + jnz 1f; \ + lock; \ + btrl $0, SYMBOL_NAME(kernel_flag); \ +1: popfl; + +/* macro ENTER_KERNEL waits for entering the kernel, increments + kernel_counter, and reloads the processor variables if necessary + uses : %eax, %edx (pushed and popped) + + Note: We go to great pains to minimise the number of locked operations. + We want to spin without locking, and lock when we attempt an update. + The pentium has a MESI cache so the spin without lock will exit when + another CPU write invalidates our cache, and the lock is avoided when + possible so we don't play ping-pong games with the cache line. + +*/ + +#ifndef __SMP_PROF__ + +#define SMP_PROF_A +#define SMP_PROF_B + +#else + +#define SMP_PROF_A movl $0,SYMBOL_NAME(smp_spins_syscall_cur)(,%eax,4); +#define SMP_PROF_B incl SYMBOL_NAME(smp_spins_syscall)(,%eax,4); \ + incl SYMBOL_NAME(smp_spins_syscall_cur)(,%eax,4); +#endif + +#define ENTER_KERNEL \ + pushl %eax; \ + pushl %ebx; \ + pushl %ecx; \ + pushl %edx; \ + pushfl; \ + cli; \ + movl $6000, %ebx; \ + movl SYMBOL_NAME(smp_loops_per_tick), %ecx; \ + GET_PROCESSOR_ID \ + btsl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \ + SMP_PROF_A \ +1: lock; \ + btsl $0, SYMBOL_NAME(kernel_flag); \ + jnc 3f; \ + cmpb SYMBOL_NAME(active_kernel_processor), %al; \ + je 4f; \ +2: SMP_PROF_B \ + btl %eax, SYMBOL_NAME(smp_invalidate_needed); \ + jnc 5f; \ + lock; \ + btrl %eax, SYMBOL_NAME(smp_invalidate_needed); \ + jnc 5f; \ + movl %cr3,%edx; \ + movl %edx,%cr3; \ +5: sti; \ + decl %ecx; \ + cli; \ + jne 7f; \ + decl %ebx; \ + jne 6f; \ + call SYMBOL_NAME(non_irq_deadlock_detected); \ +6: movl SYMBOL_NAME(smp_loops_per_tick), %ecx; \ + cmpb SYMBOL_NAME(boot_cpu_id), %al; \ + jne 7f; \ + incl SYMBOL_NAME(jiffies); \ +7: btl $0, SYMBOL_NAME(kernel_flag); \ + jc 2b; \ + jmp 1b; \ +3: movb %al, SYMBOL_NAME(active_kernel_processor); \ +4: incl SYMBOL_NAME(kernel_counter); \ + incl SYMBOL_NAME(syscall_count); \ + popfl; \ + popl %edx; \ + popl %ecx; \ + popl %ebx; \ + popl %eax; + + +#define RESTORE_ALL \ + cmpw $(KERNEL_CS),CS(%esp); \ + je 1f; \ + GET_PROCESSOR_OFFSET(%edx) \ + movl SYMBOL_NAME(current_set)(,%edx), %eax ; ; \ + movl dbgreg7(%eax),%ebx; \ + movl %ebx,%db7; \ +1: LEAVE_KERNEL \ + popl %ebx; \ + popl %ecx; \ + popl %edx; \ + popl %esi; \ + popl %edi; \ + popl %ebp; \ + popl %eax; \ + pop %ds; \ + pop %es; \ + pop %fs; \ + pop %gs; \ + addl $4,%esp; \ + iret + +#else + +#define RESTORE_ALL \ + cmpw $(KERNEL_CS),CS(%esp); \ + je 1f; \ + movl SYMBOL_NAME(current_set),%eax; \ + movl dbgreg7(%eax),%ebx; \ + movl %ebx,%db7; \ +1: \ + popl %ebx; \ + popl %ecx; \ + popl %edx; \ + popl %esi; \ + popl %edi; \ + popl %ebp; \ + popl %eax; \ + pop %ds; \ + pop %es; \ + pop %fs; \ + pop %gs; \ + addl $4,%esp; \ + iret +#endif + +ENTRY(lcall7) + pushfl # We get a different stack layout with call gates, + pushl %eax # which has to be cleaned up later.. + SAVE_ALL +#ifdef __SMP__ + ENTER_KERNEL +#endif + movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. + movl CS(%esp),%edx # this is eip.. + movl EFLAGS(%esp),%ecx # and this is cs.. + movl %eax,EFLAGS(%esp) # + movl %edx,EIP(%esp) # Now we move them to their "normal" places + movl %ecx,CS(%esp) # + movl %esp,%eax +#ifdef __SMP__ + GET_PROCESSOR_OFFSET(%edx) # Processor offset into edx + movl SYMBOL_NAME(current_set)(,%edx),%edx +#else + movl SYMBOL_NAME(current_set),%edx +#endif + pushl %eax + movl exec_domain(%edx),%edx # Get the execution domain + movl 4(%edx),%edx # Get the lcall7 handler for the domain + call *%edx + popl %eax + jmp ret_from_sys_call + + ALIGN +handle_bottom_half: + incl SYMBOL_NAME(intr_count) + call SYMBOL_NAME(do_bottom_half) + decl SYMBOL_NAME(intr_count) + jmp 9f + ALIGN +reschedule: + pushl $ret_from_sys_call + jmp SYMBOL_NAME(schedule) # test + +ENTRY(system_call) + pushl %eax # save orig_eax + SAVE_ALL +#ifdef __SMP__ + ENTER_KERNEL +#endif + movl $-ENOSYS,EAX(%esp) + cmpl $(NR_syscalls),%eax + jae ret_from_sys_call + movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax + testl %eax,%eax + je ret_from_sys_call +#ifdef __SMP__ + GET_PROCESSOR_OFFSET(%edx) + movl SYMBOL_NAME(current_set)(,%edx),%ebx +#else + movl SYMBOL_NAME(current_set),%ebx +#endif + andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors + movl %db6,%edx + movl %edx,dbgreg6(%ebx) # save current hardware debugging status + testb $0x20,flags(%ebx) # PF_TRACESYS + jne 1f + call *%eax + movl %eax,EAX(%esp) # save the return value + jmp ret_from_sys_call + ALIGN +1: call SYMBOL_NAME(syscall_trace) + movl ORIG_EAX(%esp),%eax + call SYMBOL_NAME(sys_call_table)(,%eax,4) + movl %eax,EAX(%esp) # save the return value +#ifdef __SMP__ + GET_PROCESSOR_OFFSET(%eax) + movl SYMBOL_NAME(current_set)(,%eax),%eax +#else + movl SYMBOL_NAME(current_set),%eax +#endif + call SYMBOL_NAME(syscall_trace) + + ALIGN + .globl ret_from_sys_call +ret_from_sys_call: + cmpl $0,SYMBOL_NAME(intr_count) + jne 2f +9: movl SYMBOL_NAME(bh_mask),%eax + andl SYMBOL_NAME(bh_active),%eax + jne handle_bottom_half +#ifdef __SMP__ + cmpb $(NO_PROC_ID), SYMBOL_NAME(saved_active_kernel_processor) + jne 2f +#endif + movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are + testl $(VM_MASK),%eax # different then + jne 1f + cmpw $(KERNEL_CS),CS(%esp) # was old code segment supervisor ? + je 2f +1: sti + orl $(IF_MASK),%eax # these just try to make sure + andl $~NT_MASK,%eax # the program doesn't do anything + movl %eax,EFLAGS(%esp) # stupid + cmpl $0,SYMBOL_NAME(need_resched) + jne reschedule +#ifdef __SMP__ + GET_PROCESSOR_OFFSET(%eax) + movl SYMBOL_NAME(current_set)(,%eax), %eax +#else + movl SYMBOL_NAME(current_set),%eax +#endif + cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals + je 2f + movl blocked(%eax),%ecx + movl %ecx,%ebx # save blocked in %ebx for signal handling + notl %ecx + andl signal(%eax),%ecx + jne signal_return +2: RESTORE_ALL + ALIGN +signal_return: + movl %esp,%ecx + pushl %ecx + testl $(VM_MASK),EFLAGS(%ecx) + jne v86_signal_return + pushl %ebx + call SYMBOL_NAME(do_signal) + popl %ebx + popl %ebx + RESTORE_ALL + ALIGN +v86_signal_return: + call SYMBOL_NAME(save_v86_state) + movl %eax,%esp + pushl %eax + pushl %ebx + call SYMBOL_NAME(do_signal) + popl %ebx + popl %ebx + RESTORE_ALL + +ENTRY(divide_error) + pushl $0 # no error code + pushl $ SYMBOL_NAME(do_divide_error) + ALIGN +error_code: + push %fs + push %es + push %ds + pushl %eax + xorl %eax,%eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + decl %eax # eax = -1 + pushl %ecx + pushl %ebx + cld + xorl %ebx,%ebx # zero ebx + xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) + mov %gs,%bx # get the lower order bits of gs + movl %esp,%edx + xchgl %ebx, GS(%esp) # get the address and save gs. + pushl %eax # push the error code + pushl %edx + movl $(KERNEL_DS),%edx + mov %dx,%ds + mov %dx,%es + movl $(USER_DS),%edx + mov %dx,%fs +#ifdef __SMP__ + ENTER_KERNEL + GET_PROCESSOR_OFFSET(%eax) + movl SYMBOL_NAME(current_set)(,%eax), %eax +#else + movl SYMBOL_NAME(current_set),%eax +#endif + movl %db6,%edx + movl %edx,dbgreg6(%eax) # save current hardware debugging status + call *%ebx + addl $8,%esp + jmp ret_from_sys_call + +ENTRY(coprocessor_error) + pushl $0 + pushl $ SYMBOL_NAME(do_coprocessor_error) + jmp error_code + +ENTRY(device_not_available) + pushl $-1 # mark this as an int + SAVE_ALL +#ifdef __SMP__ + ENTER_KERNEL +#endif + pushl $ret_from_sys_call + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je SYMBOL_NAME(math_state_restore) + pushl $0 # temporary storage for ORIG_EIP + call SYMBOL_NAME(math_emulate) + addl $4,%esp + ret + +ENTRY(debug) + pushl $0 + pushl $ SYMBOL_NAME(do_debug) + jmp error_code + +ENTRY(nmi) + pushl $0 + pushl $ SYMBOL_NAME(do_nmi) + jmp error_code + +ENTRY(int3) + pushl $0 + pushl $ SYMBOL_NAME(do_int3) + jmp error_code + +ENTRY(overflow) + pushl $0 + pushl $ SYMBOL_NAME(do_overflow) + jmp error_code + +ENTRY(bounds) + pushl $0 + pushl $ SYMBOL_NAME(do_bounds) + jmp error_code + +ENTRY(invalid_op) + pushl $0 + pushl $ SYMBOL_NAME(do_invalid_op) + jmp error_code + +ENTRY(coprocessor_segment_overrun) + pushl $0 + pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun) + jmp error_code + +ENTRY(reserved) + pushl $0 + pushl $ SYMBOL_NAME(do_reserved) + jmp error_code + +ENTRY(double_fault) + pushl $ SYMBOL_NAME(do_double_fault) + jmp error_code + +ENTRY(invalid_TSS) + pushl $ SYMBOL_NAME(do_invalid_TSS) + jmp error_code + +ENTRY(segment_not_present) + pushl $ SYMBOL_NAME(do_segment_not_present) + jmp error_code + +ENTRY(stack_segment) + pushl $ SYMBOL_NAME(do_stack_segment) + jmp error_code + +ENTRY(general_protection) + pushl $ SYMBOL_NAME(do_general_protection) + jmp error_code + +ENTRY(alignment_check) + pushl $ SYMBOL_NAME(do_alignment_check) + jmp error_code + +ENTRY(page_fault) + pushl $ SYMBOL_NAME(do_page_fault) + jmp error_code + +ENTRY(spurious_interrupt_bug) + pushl $0 + pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) + jmp error_code + +.data +ENTRY(sys_call_table) + .long SYMBOL_NAME(sys_setup) /* 0 */ + .long SYMBOL_NAME(sys_exit) + .long SYMBOL_NAME(sys_fork) + .long SYMBOL_NAME(sys_read) + .long SYMBOL_NAME(sys_write) + .long SYMBOL_NAME(sys_open) /* 5 */ + .long SYMBOL_NAME(sys_close) + .long SYMBOL_NAME(sys_waitpid) + .long SYMBOL_NAME(sys_creat) + .long SYMBOL_NAME(sys_link) + .long SYMBOL_NAME(sys_unlink) /* 10 */ + .long SYMBOL_NAME(sys_execve) + .long SYMBOL_NAME(sys_chdir) + .long SYMBOL_NAME(sys_time) + .long SYMBOL_NAME(sys_mknod) + .long SYMBOL_NAME(sys_chmod) /* 15 */ + .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_break) + .long SYMBOL_NAME(sys_stat) + .long SYMBOL_NAME(sys_lseek) + .long SYMBOL_NAME(sys_getpid) /* 20 */ + .long SYMBOL_NAME(sys_mount) + .long SYMBOL_NAME(sys_umount) + .long SYMBOL_NAME(sys_setuid) + .long SYMBOL_NAME(sys_getuid) + .long SYMBOL_NAME(sys_stime) /* 25 */ + .long SYMBOL_NAME(sys_ptrace) + .long SYMBOL_NAME(sys_alarm) + .long SYMBOL_NAME(sys_fstat) + .long SYMBOL_NAME(sys_pause) + .long SYMBOL_NAME(sys_utime) /* 30 */ + .long SYMBOL_NAME(sys_stty) + .long SYMBOL_NAME(sys_gtty) + .long SYMBOL_NAME(sys_access) + .long SYMBOL_NAME(sys_nice) + .long SYMBOL_NAME(sys_ftime) /* 35 */ + .long SYMBOL_NAME(sys_sync) + .long SYMBOL_NAME(sys_kill) + .long SYMBOL_NAME(sys_rename) + .long SYMBOL_NAME(sys_mkdir) + .long SYMBOL_NAME(sys_rmdir) /* 40 */ + .long SYMBOL_NAME(sys_dup) + .long SYMBOL_NAME(sys_pipe) + .long SYMBOL_NAME(sys_times) + .long SYMBOL_NAME(sys_prof) + .long SYMBOL_NAME(sys_brk) /* 45 */ + .long SYMBOL_NAME(sys_setgid) + .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_signal) + .long SYMBOL_NAME(sys_geteuid) + .long SYMBOL_NAME(sys_getegid) /* 50 */ + .long SYMBOL_NAME(sys_acct) + .long SYMBOL_NAME(sys_phys) + .long SYMBOL_NAME(sys_lock) + .long SYMBOL_NAME(sys_ioctl) + .long SYMBOL_NAME(sys_fcntl) /* 55 */ + .long SYMBOL_NAME(sys_mpx) + .long SYMBOL_NAME(sys_setpgid) + .long SYMBOL_NAME(sys_ulimit) + .long SYMBOL_NAME(sys_olduname) + .long SYMBOL_NAME(sys_umask) /* 60 */ + .long SYMBOL_NAME(sys_chroot) + .long SYMBOL_NAME(sys_ustat) + .long SYMBOL_NAME(sys_dup2) + .long SYMBOL_NAME(sys_getppid) + .long SYMBOL_NAME(sys_getpgrp) /* 65 */ + .long SYMBOL_NAME(sys_setsid) + .long SYMBOL_NAME(sys_sigaction) + .long SYMBOL_NAME(sys_sgetmask) + .long SYMBOL_NAME(sys_ssetmask) + .long SYMBOL_NAME(sys_setreuid) /* 70 */ + .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_sigsuspend) + .long SYMBOL_NAME(sys_sigpending) + .long SYMBOL_NAME(sys_sethostname) + .long SYMBOL_NAME(sys_setrlimit) /* 75 */ + .long SYMBOL_NAME(sys_getrlimit) + .long SYMBOL_NAME(sys_getrusage) + .long SYMBOL_NAME(sys_gettimeofday) + .long SYMBOL_NAME(sys_settimeofday) + .long SYMBOL_NAME(sys_getgroups) /* 80 */ + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(old_select) + .long SYMBOL_NAME(sys_symlink) + .long SYMBOL_NAME(sys_lstat) + .long SYMBOL_NAME(sys_readlink) /* 85 */ + .long SYMBOL_NAME(sys_uselib) + .long SYMBOL_NAME(sys_swapon) + .long SYMBOL_NAME(sys_reboot) + .long SYMBOL_NAME(old_readdir) + .long SYMBOL_NAME(old_mmap) /* 90 */ + .long SYMBOL_NAME(sys_munmap) + .long SYMBOL_NAME(sys_truncate) + .long SYMBOL_NAME(sys_ftruncate) + .long SYMBOL_NAME(sys_fchmod) + .long SYMBOL_NAME(sys_fchown) /* 95 */ + .long SYMBOL_NAME(sys_getpriority) + .long SYMBOL_NAME(sys_setpriority) + .long SYMBOL_NAME(sys_profil) + .long SYMBOL_NAME(sys_statfs) + .long SYMBOL_NAME(sys_fstatfs) /* 100 */ + .long SYMBOL_NAME(sys_ioperm) + .long SYMBOL_NAME(sys_socketcall) + .long SYMBOL_NAME(sys_syslog) + .long SYMBOL_NAME(sys_setitimer) + .long SYMBOL_NAME(sys_getitimer) /* 105 */ + .long SYMBOL_NAME(sys_newstat) + .long SYMBOL_NAME(sys_newlstat) + .long SYMBOL_NAME(sys_newfstat) + .long SYMBOL_NAME(sys_uname) + .long SYMBOL_NAME(sys_iopl) /* 110 */ + .long SYMBOL_NAME(sys_vhangup) + .long SYMBOL_NAME(sys_idle) + .long SYMBOL_NAME(sys_vm86old) + .long SYMBOL_NAME(sys_wait4) + .long SYMBOL_NAME(sys_swapoff) /* 115 */ + .long SYMBOL_NAME(sys_sysinfo) + .long SYMBOL_NAME(sys_ipc) + .long SYMBOL_NAME(sys_fsync) + .long SYMBOL_NAME(sys_sigreturn) + .long SYMBOL_NAME(sys_clone) /* 120 */ + .long SYMBOL_NAME(sys_setdomainname) + .long SYMBOL_NAME(sys_newuname) + .long SYMBOL_NAME(sys_modify_ldt) + .long SYMBOL_NAME(sys_adjtimex) + .long SYMBOL_NAME(sys_mprotect) /* 125 */ + .long SYMBOL_NAME(sys_sigprocmask) + .long SYMBOL_NAME(sys_create_module) + .long SYMBOL_NAME(sys_init_module) + .long SYMBOL_NAME(sys_delete_module) + .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */ + .long SYMBOL_NAME(sys_quotactl) + .long SYMBOL_NAME(sys_getpgid) + .long SYMBOL_NAME(sys_fchdir) + .long SYMBOL_NAME(sys_bdflush) + .long SYMBOL_NAME(sys_sysfs) /* 135 */ + .long SYMBOL_NAME(sys_personality) + .long 0 /* for afs_syscall */ + .long SYMBOL_NAME(sys_setfsuid) + .long SYMBOL_NAME(sys_setfsgid) + .long SYMBOL_NAME(sys_llseek) /* 140 */ + .long SYMBOL_NAME(sys_getdents) + .long SYMBOL_NAME(sys_select) + .long SYMBOL_NAME(sys_flock) + .long SYMBOL_NAME(sys_msync) + .long SYMBOL_NAME(sys_readv) /* 145 */ + .long SYMBOL_NAME(sys_writev) + .long SYMBOL_NAME(sys_getsid) + .long SYMBOL_NAME(sys_fdatasync) + .long SYMBOL_NAME(sys_sysctl) + .long SYMBOL_NAME(sys_mlock) /* 150 */ + .long SYMBOL_NAME(sys_munlock) + .long SYMBOL_NAME(sys_mlockall) + .long SYMBOL_NAME(sys_munlockall) + .long SYMBOL_NAME(sys_sched_setparam) + .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ + .long SYMBOL_NAME(sys_sched_setscheduler) + .long SYMBOL_NAME(sys_sched_getscheduler) + .long SYMBOL_NAME(sys_sched_yield) + .long SYMBOL_NAME(sys_sched_get_priority_max) + .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ + .long SYMBOL_NAME(sys_sched_rr_get_interval) + .long SYMBOL_NAME(sys_nanosleep) + .long SYMBOL_NAME(sys_mremap) + .long 0,0 + .long SYMBOL_NAME(sys_vm86) + .long 0,0,0,0 /* 170 */ + .long 0,0,0,0,0,0,0,0,0,0 /* 180 */ + .long 0,0,0,0,0,0,0 + .long SYMBOL_NAME(sys_table) + .space (NR_syscalls-188)*4 diff --git a/kernel/table20/kernel.patch b/kernel/table20/kernel.patch new file mode 100644 index 00000000..37654b3d --- /dev/null +++ b/kernel/table20/kernel.patch @@ -0,0 +1,51 @@ +diff -ur linux-2.0.32/Makefile linux-hacked/Makefile +--- linux-2.0.32/Makefile Fri Nov 7 19:51:05 1997 ++++ linux-hacked/Makefile Thu Jun 11 20:41:12 1998 +@@ -87,7 +87,7 @@ + # standard CFLAGS + # + +-CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce ++CFLAGS = -Wall -Wstrict-prototypes -g -O2 -fomit-frame-pointer -fno-strength-reduce + + ifdef CONFIG_CPP + CFLAGS := $(CFLAGS) -x c++ +@@ -113,12 +113,12 @@ + # Include the make variables (CC, etc...) + # + +-ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o net/network.a ++ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o net/network.a table/table.o + FILESYSTEMS =fs/filesystems.a + DRIVERS =drivers/block/block.a \ + drivers/char/char.a + LIBS =$(TOPDIR)/lib/lib.a +-SUBDIRS =kernel drivers mm fs net ipc lib ++SUBDIRS =kernel drivers mm fs net ipc lib table + + ifeq ($(CONFIG_ISDN),y) + DRIVERS := $(DRIVERS) drivers/isdn/isdn.a +diff -ur linux-2.0.32/arch/i386/kernel/entry.S linux-hacked/arch/i386/kernel/entry.S +--- linux-2.0.32/arch/i386/kernel/entry.S Tue Sep 16 23:42:45 1997 ++++ linux-hacked/arch/i386/kernel/entry.S Thu Jun 11 21:37:20 1998 +@@ -699,4 +699,8 @@ + .long SYMBOL_NAME(sys_mremap) + .long 0,0 + .long SYMBOL_NAME(sys_vm86) +- .space (NR_syscalls-166)*4 ++ .long 0,0,0,0 /* 170 */ ++ .long 0,0,0,0,0,0,0,0,0,0 /* 180 */ ++ .long 0,0,0,0,0,0,0 ++ .long SYMBOL_NAME(sys_table) ++ .space (NR_syscalls-188)*4 +diff -ur linux-2.0.32/include/asm-i386/unistd.h linux-hacked/include/asm-i386/unistd.h +--- linux-2.0.32/include/asm-i386/unistd.h Fri Mar 22 07:34:02 1996 ++++ linux-hacked/include/asm-i386/unistd.h Thu Jun 11 21:37:03 1998 +@@ -169,6 +169,7 @@ + #define __NR_sched_rr_get_interval 161 + #define __NR_nanosleep 162 + #define __NR_mremap 163 ++#define __NR_table 188 + + /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ + #define _syscall0(type,name) \ diff --git a/kernel/table20/main.c b/kernel/table20/main.c new file mode 100644 index 00000000..97950afb --- /dev/null +++ b/kernel/table20/main.c @@ -0,0 +1,468 @@ +/* + * linux/table/table_impl.c + * Copyright (C) 1998 Martin Baulig + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/tty.h> +#include <linux/user.h> +#include <linux/a.out.h> +#include <linux/string.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <linux/ioport.h> +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/swap.h> + +#include <asm/segment.h> +#include <asm/pgtable.h> +#include <asm/io.h> + +#include <linux/table.h> + +#include "version.h" + +#if defined(__i386__) +# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019]) +# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022]) +#elif defined(__alpha__) + /* + * See arch/alpha/kernel/ptrace.c for details. + */ +# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + + (long)&((struct pt_regs *)0)->reg) +# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc))) +# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(__sparc__) +# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + + (long)&((struct pt_regs *)0)->reg) +# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc))) +# define KSTK_ESP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(u_regs[UREG_FP]))) +#endif + +static struct task_struct * +get_task (pid_t pid) +{ + struct task_struct ** p; + + p = task; + while (++p < task+NR_TASKS) { + if (*p && (*p)->pid == pid) + return *p; + } + + return NULL; +} + +static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pte_t * pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd)); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t page = *pte; + + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + ++*total; + if (!pte_present(page)) + continue; + ++*pages; + if (pte_dirty(page)) + ++*dirty; + if (pte_page(page) >= high_memory) + continue; + if (mem_map[MAP_NR(pte_page(page))].count > 1) + ++*shared; + } while (address < end); +} + +static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pmd_t * pmd; + unsigned long end; + + if (pgd_none(*pgd)) + return; + if (pgd_bad(*pgd)) { + printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd)); + pgd_clear(pgd); + return; + } + pmd = pmd_offset(pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + statm_pte_range(pmd, address, end - address, pages, shared, dirty, total); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end, + int * pages, int * shared, int * dirty, int * total) +{ + while (address < end) { + statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + pgd++; + } +} + +static unsigned long +get_wchan (struct task_struct *p) +{ + if (!p || p == current || p->state == TASK_RUNNING) + return 0; +#if defined(__i386__) + { + unsigned long ebp, eip; + unsigned long stack_page; + int count = 0; + + stack_page = p->kernel_stack_page; + if (!stack_page) + return 0; + ebp = p->tss.ebp; + do { + if (ebp < stack_page || ebp >= 4092+stack_page) + return 0; + eip = *(unsigned long *) (ebp+4); + if (eip < (unsigned long) interruptible_sleep_on + || eip >= (unsigned long) add_timer) + return eip; + ebp = *(unsigned long *) ebp; + } while (count++ < 16); + } +#elif defined(__alpha__) + /* + * This one depends on the frame size of schedule(). Do a + * "disass schedule" in gdb to find the frame size. Also, the + * code assumes that sleep_on() follows immediately after + * interruptible_sleep_on() and that add_timer() follows + * immediately after interruptible_sleep(). Ugly, isn't it? + * Maybe adding a wchan field to task_struct would be better, + * after all... + */ + { + unsigned long schedule_frame; + unsigned long pc; + + pc = thread_saved_pc(&p->tss); + if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { + schedule_frame = ((unsigned long *)p->tss.ksp)[6]; + return ((unsigned long *)schedule_frame)[12]; + } + return pc; + } +#endif + return 0; +} + +asmlinkage int +sys_table (int type, union table *buf, const void *param) +{ + union table tbl; + struct sysinfo i; + struct task_struct *tsk = NULL; + struct ip_chain *chain; + struct ip_fwkernel *rule; + char devname [9]; + int index, err; + pid_t pid; + + if (type == TABLE_VERSION) + return _TABLE_VERSION; + + if (!buf) + return -EFAULT; + + memset (&tbl, 0, sizeof (union table)); + + /* For TABLE_PROC_*, read pid and get task_struct */ + + switch (type) { + case TABLE_PROC_UID: + case TABLE_PROC_MEM: + case TABLE_PROC_SEGMENT: + case TABLE_PROC_TIME: + case TABLE_PROC_STATE: + case TABLE_PROC_SIGNAL: + case TABLE_PROC_KERNEL: + err = verify_area (VERIFY_READ, param, sizeof (pid_t)); + if (err) + return err; + memcpy_fromfs (&pid, param, sizeof (pid_t)); + + tsk = get_task (pid); + if (tsk == NULL) + return -ESRCH; + break; + case TABLE_NETACCT: + err = verify_area (VERIFY_READ, param, 5); + if (err) + return err; + copy_from_user (devname, param, 5); + devname [5] = 0; + + break; + } + + /* Main function dispatcher */ + + switch (type) { + case TABLE_PROCLIST: + tsk = task [0]; + for (index = 0; index < nr_tasks; index++) { + tbl.proclist.pids [index] = tsk->pid; + tsk = tsk->next_task; + } + tbl.proclist.nr_running = nr_running; + tbl.proclist.nr_tasks = nr_tasks; + tbl.proclist.last_pid = last_pid; + break; + case TABLE_CPU: + tbl.cpu.total = jiffies; + tbl.cpu.user = kstat.cpu_user; + tbl.cpu.nice = kstat.cpu_nice; + tbl.cpu.sys = kstat.cpu_system; + tbl.cpu.idle = tbl.cpu.total - + (tbl.cpu.user + tbl.cpu.nice + tbl.cpu.sys); + tbl.cpu.frequency = HZ; + break; + case TABLE_MEM: + si_meminfo (&i); + tbl.mem.total = i.totalram; + tbl.mem.used = i.totalram - i.freeram; + tbl.mem.free = i.freeram; + tbl.mem.shared = i.sharedram; + tbl.mem.buffer = i.bufferram; + tbl.mem.cached = page_cache_size << PAGE_SHIFT; + break; + case TABLE_SWAP: + si_swapinfo (&i); + tbl.swap.total = i.totalswap; + tbl.swap.used = i.totalswap - i.freeswap; + tbl.swap.free = i.freeswap; + tbl.swap.pagein = kstat.pswpin; + tbl.swap.pageout = kstat.pswpout; + break; + case TABLE_LOADAVG: + tbl.loadavg.loadavg [0] = (double) avenrun [0] / (1 << FSHIFT); + tbl.loadavg.loadavg [1] = (double) avenrun [1] / (1 << FSHIFT); + tbl.loadavg.loadavg [2] = (double) avenrun [2] / (1 << FSHIFT); + tbl.loadavg.nr_running = nr_running; + tbl.loadavg.nr_tasks = nr_tasks; + tbl.loadavg.last_pid = last_pid; + break; + case TABLE_UPTIME: + tbl.uptime.uptime = jiffies; + tbl.uptime.idle = task[0]->utime + task[0]->stime; + break; + case TABLE_PROC_STATE: + tbl.proc_state.state = tsk->state; + tbl.proc_state.flags = tsk->flags; + memcpy (tbl.proc_state.comm, tsk->comm, + sizeof (tbl.proc_state.comm)); + break; + case TABLE_PROC_UID: + tbl.proc_uid.uid = tsk->uid; + tbl.proc_uid.euid = tsk->euid; + tbl.proc_uid.suid = tsk->suid; + tbl.proc_uid.fsuid = tsk->fsuid; + + tbl.proc_uid.gid = tsk->gid; + tbl.proc_uid.egid = tsk->egid; + tbl.proc_uid.sgid = tsk->sgid; + tbl.proc_uid.fsgid = tsk->fsgid; + + tbl.proc_uid.pid = tsk->pid; + tbl.proc_uid.pgrp = tsk->pgrp; + tbl.proc_uid.ppid = tsk->p_pptr->pid; + + tbl.proc_uid.session = tsk->session; + tbl.proc_uid.tty = tsk->tty ? + kdev_t_to_nr (tsk->tty->device) : 0; + tbl.proc_uid.tpgid = tsk->tty ? tsk->tty->pgrp : -1; + + tbl.proc_uid.priority = tsk->priority; + tbl.proc_uid.counter = tsk->counter; + tbl.proc_uid.def_priority = DEF_PRIORITY; + break; + case TABLE_PROC_SIGNAL: + tbl.proc_signal.signal = tsk->signal; + tbl.proc_signal.blocked = tsk->blocked; + + if (tsk->sig) { + struct sigaction * action = tsk->sig->action; + unsigned long sig_ign = 0, sig_caught = 0; + unsigned long bit = 1; + int i; + + for (i = 0; i < 32; i++) { + switch((unsigned long) action->sa_handler) { + case 0: + break; + case 1: + sig_ign |= bit; + break; + default: + sig_caught |= bit; + } + bit <<= 1; + action++; + } + + tbl.proc_signal.ignored = sig_ign; + tbl.proc_signal.caught = sig_caught; + } else { + tbl.proc_signal.ignored = 0; + tbl.proc_signal.caught = 0; + } + break; + case TABLE_PROC_MEM: + if (tsk->mm && tsk->mm != &init_mm) { + tbl.proc_mem.context = tsk->mm->context; + tbl.proc_mem.start_code = tsk->mm->start_code; + tbl.proc_mem.end_code = tsk->mm->end_code; + tbl.proc_mem.start_data = tsk->mm-> start_data; + tbl.proc_mem.end_data = tsk->mm->end_data; + tbl.proc_mem.start_brk = tsk->mm->start_brk; + tbl.proc_mem.brk = tsk->mm->brk; + tbl.proc_mem.start_stack = tsk->mm->start_stack; + tbl.proc_mem.start_mmap = tsk->mm->start_mmap; + tbl.proc_mem.arg_start = tsk->mm->arg_start; + tbl.proc_mem.arg_end = tsk->mm->arg_end; + tbl.proc_mem.env_start = tsk->mm->env_start; + tbl.proc_mem.env_end = tsk->mm->env_end; + tbl.proc_mem.rss = tsk->mm->rss; + tbl.proc_mem.total_vm = tsk->mm->total_vm; + tbl.proc_mem.locked_vm = tsk->mm->locked_vm; + } + tbl.proc_mem.rlim = tsk->rlim ? + tsk->rlim[RLIMIT_RSS].rlim_cur : 0; + break; + case TABLE_PROC_SEGMENT: + if (tsk->mm && tsk->mm != &init_mm) { + unsigned long vsize = 0; + int size = 0, resident = 0, share = 0; + int trs = 0, lrs = 0, drs = 0, dt = 0; + struct vm_area_struct * vma = tsk->mm->mmap; + + while (vma) { + pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start); + int pages = 0, shared = 0, dirty = 0, total = 0; + + vsize += vma->vm_end - vma->vm_start; + + statm_pgd_range (pgd, vma->vm_start, vma->vm_end, + &pages, &shared, &dirty, &total); + resident += pages; + share += shared; + dt += dirty; + size += total; + if (vma->vm_flags & VM_EXECUTABLE) + trs += pages; /* text */ + else if (vma->vm_flags & VM_GROWSDOWN) + drs += pages; /* stack */ + else if (vma->vm_end > 0x60000000) + lrs += pages; /* library */ + else + drs += pages; + vma = vma->vm_next; + } + + tbl.proc_segment.vsize = vsize; + tbl.proc_segment.size = size; + tbl.proc_segment.resident = resident; + tbl.proc_segment.shared = share; + tbl.proc_segment.trs = trs; + tbl.proc_segment.lrs = lrs; + tbl.proc_segment.dt = dt; + } + break; + case TABLE_PROC_TIME: + tbl.proc_time.utime = tsk->utime; + tbl.proc_time.stime = tsk->stime; + tbl.proc_time.cutime = tsk->cutime; + tbl.proc_time.cstime = tsk->cstime; + + tbl.proc_time.start_time = tsk->start_time; + tbl.proc_time.timeout = tsk->timeout; + tbl.proc_time.policy = tsk->policy; + tbl.proc_time.rt_priority = tsk->rt_priority; + + tbl.proc_time.it_real_value = tsk->it_real_value; + tbl.proc_time.it_prof_value = tsk->it_prof_value; + tbl.proc_time.it_virt_value = tsk->it_virt_value; + tbl.proc_time.it_real_incr = tsk->it_real_incr; + tbl.proc_time.it_prof_incr = tsk->it_prof_incr; + tbl.proc_time.it_virt_incr = tsk->it_virt_incr; + break; + case TABLE_PROC_KERNEL: + tbl.proc_kernel.min_flt = tsk->min_flt; + tbl.proc_kernel.cmin_flt = tsk->cmin_flt; + tbl.proc_kernel.maj_flt = tsk->maj_flt; + tbl.proc_kernel.cmaj_flt = tsk->cmaj_flt; + + tbl.proc_kernel.kesp = tsk->kernel_stack_page ? KSTK_EIP(tsk) : 0; + tbl.proc_kernel.keip = tsk->kernel_stack_page ? KSTK_ESP(tsk) : 0; + + tbl.proc_kernel.nswap = tsk->nswap; + tbl.proc_kernel.cnswap = tsk->cnswap; + + tbl.proc_kernel.wchan = get_wchan (tsk); + break; + case TABLE_NETACCT: + for (chain = ip_fw_chains; chain; chain = chain->next) { + for (rule = chain->chain; rule; rule = rule->next) { + const char *name = rule->ipfw.fw_vianame; + int k; + + if (name [0] && !strncmp (param, name, 5)) + continue; + + for (k = 0; k < NUM_SLOTS; k++) { + tbl.netacct.packets += + rule->counters[k].pcnt; + tbl.netacct.bytes += + rule->counters[k].bcnt; + } + } + } + break; + default: + return -EINVAL; + } + + err = verify_area (VERIFY_WRITE, buf, sizeof (struct table)); + if (err) + return err; + + memcpy_tofs (buf, &tbl, sizeof (union table)); + return 0; +} diff --git a/kernel/table20/unistd-i386.h b/kernel/table20/unistd-i386.h new file mode 100644 index 00000000..0d5b4f8b --- /dev/null +++ b/kernel/table20/unistd-i386.h @@ -0,0 +1,324 @@ +#ifndef _ASM_I386_UNISTD_H_ +#define _ASM_I386_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_setup 0 /* used only by init, to get system going */ +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_phys 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_profil 98 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86 113 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_modify_ldt 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_table 188 + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define _syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +if (__res >= 0) \ + return (type) __res; \ +errno = -__res; \ +return -1; \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +if (__res >= 0) \ + return (type) __res; \ +errno = -__res; \ +return -1; \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ +if (__res >= 0) \ + return (type) __res; \ +errno = -__res; \ +return -1; \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +if (__res>=0) \ + return (type) __res; \ +errno=-__res; \ +return -1; \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +if (__res>=0) \ + return (type) __res; \ +errno=-__res; \ +return -1; \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +if (__res>=0) \ + return (type) __res; \ +errno=-__res; \ +return -1; \ +} + +#ifdef __KERNEL_SYSCALLS__ + +/* + * we need this inline - forking from kernel space will result + * in NO COPY ON WRITE (!!!), until an execve is executed. This + * is no problem, but for the stack. This is handled by not letting + * main() use the stack at all after fork(). Thus, no function + * calls - which means inline code for fork too, as otherwise we + * would use the stack upon exit from 'fork()'. + * + * Actually only pause and fork are needed inline, so that there + * won't be any messing with the stack from main(), but we define + * some others too. + */ +#define __NR__exit __NR_exit +static inline _syscall0(int,idle) +static inline _syscall0(int,fork) +static inline _syscall2(int,clone,unsigned long,flags,char *,esp) +static inline _syscall0(int,pause) +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) +static inline _syscall1(int,dup,int,fd) +static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) +static inline _syscall3(int,open,const char *,file,int,flag,int,mode) +static inline _syscall1(int,close,int,fd) +static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) + +static inline pid_t wait(int * wait_stat) +{ + return waitpid(-1,wait_stat,0); +} + +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be free'd until both the parent and the child have exited. + */ +static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + "movl %%esp,%%esi\n\t" + "int $0x80\n\t" /* Linux/i386 system call */ + "cmpl %%esp,%%esi\n\t" /* child or parent? */ + "je 1f\n\t" /* parent - jump */ + "pushl %3\n\t" /* push argument */ + "call *%4\n\t" /* call fn */ + "movl %2,%0\n\t" /* exit */ + "int $0x80\n" + "1:\t" + :"=a" (retval) + :"0" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "b" (flags | CLONE_VM) + :"si"); + return retval; +} + +#endif + +#endif /* _ASM_I386_UNISTD_H_ */ diff --git a/kernel/table20/version.h b/kernel/table20/version.h new file mode 100644 index 00000000..d47411ee --- /dev/null +++ b/kernel/table20/version.h @@ -0,0 +1 @@ +#define _TABLE_VERSION 1 diff --git a/kernel/table21/.cvsignore b/kernel/table21/.cvsignore new file mode 100644 index 00000000..a7ab2843 --- /dev/null +++ b/kernel/table21/.cvsignore @@ -0,0 +1,4 @@ +kernel.patch +.main.o.flags +.table.o.flags +.module.o.flags diff --git a/kernel/table21/Makefile b/kernel/table21/Makefile new file mode 100644 index 00000000..2eedd527 --- /dev/null +++ b/kernel/table21/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the linux system information tables. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := table.o +OX_OBJS := main.o + +M_TARGET := table_mod.o +MX_OBJS := module.o + +include $(TOPDIR)/Rules.make diff --git a/kernel/table21/README b/kernel/table21/README new file mode 100644 index 00000000..88d26bec --- /dev/null +++ b/kernel/table21/README @@ -0,0 +1,21 @@ +This is a new system call `table ()' for the Linux table. It is faster +than reading from /proc and can be used to fetch all information required +for libgtop until whe have some other function (extended sysctl, ...) in +standard kernels. + +I didn't want to change sysctl or some other function myself cause this may +cause other applications relying upon those function to fail. This is +something for the ``real'' kernel gurus ... + +To use this new system call for libgtop, do the following: + +* Copy this directory to /usr/src/linux/table +* Make /usr/src/linux/include/linux/table.h symlink to /usr/src/linux/table/table.h +* Apply the patch `kernel.patch' to the kernel, compile, install and reboot +* Recompile libgtop (remove `config.cache' and run the `autogen.sh' again). + +If you want to change and/or add something - feel free to do so ! + +Have fun, + +Martin diff --git a/kernel/table21/entry-i386.S b/kernel/table21/entry-i386.S new file mode 100644 index 00000000..fb734fbc --- /dev/null +++ b/kernel/table21/entry-i386.S @@ -0,0 +1,571 @@ +/* + * linux/arch/i386/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * I changed all the .align's to 4 (16 byte alignment), as that's faster + * on a 486. + * + * Stack layout in 'ret_from_system_call': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in fork.c:copy_process, signal.c:do_signal, + * ptrace.c and ptrace.h + * + * 0(%esp) - %ebx + * 4(%esp) - %ecx + * 8(%esp) - %edx + * C(%esp) - %esi + * 10(%esp) - %edi + * 14(%esp) - %ebp + * 18(%esp) - %eax + * 1C(%esp) - %ds + * 20(%esp) - %es + * 24(%esp) - orig_eax + * 28(%esp) - %eip + * 2C(%esp) - %cs + * 30(%esp) - %eflags + * 34(%esp) - %oldesp + * 38(%esp) - %oldss + * + * "current" is in register %ebx during any slow entries. + */ + +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/segment.h> +#define ASSEMBLY +#include <asm/smp.h> + +EBX = 0x00 +ECX = 0x04 +EDX = 0x08 +ESI = 0x0C +EDI = 0x10 +EBP = 0x14 +EAX = 0x18 +DS = 0x1C +ES = 0x20 +ORIG_EAX = 0x24 +EIP = 0x28 +CS = 0x2C +EFLAGS = 0x30 +OLDESP = 0x34 +OLDSS = 0x38 + +CF_MASK = 0x00000001 +IF_MASK = 0x00000200 +NT_MASK = 0x00004000 +VM_MASK = 0x00020000 + +/* + * these are offsets into the task-struct. + */ +state = 0 +flags = 4 +sigpending = 8 +addr_limit = 12 +exec_domain = 16 +need_resched = 20 + +ENOSYS = 38 + + +#define SAVE_ALL \ + cld; \ + pushl %es; \ + pushl %ds; \ + pushl %eax; \ + pushl %ebp; \ + pushl %edi; \ + pushl %esi; \ + pushl %edx; \ + pushl %ecx; \ + pushl %ebx; \ + movl $(__KERNEL_DS),%edx; \ + movl %dx,%ds; \ + movl %dx,%es; + +#define RESTORE_ALL \ + popl %ebx; \ + popl %ecx; \ + popl %edx; \ + popl %esi; \ + popl %edi; \ + popl %ebp; \ + popl %eax; \ +1: popl %ds; \ +2: popl %es; \ +3: addl $4,%esp; \ + iret; \ +.section fixup,"ax"; \ +4: pushl $0; \ + popl %ds; \ + jmp 2b; \ +5: pushl $0; \ + popl %es; \ + jmp 3b; \ +.previous; \ +.section __ex_table,"a";\ + .align 4; \ + .long 1b,4b; \ + .long 2b,5b; \ +.previous + +#define GET_CURRENT(reg) \ + movl %esp, reg; \ + andl $-8192, reg; + +ENTRY(lcall7) + pushfl # We get a different stack layout with call gates, + pushl %eax # which has to be cleaned up later.. + SAVE_ALL + movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. + movl CS(%esp),%edx # this is eip.. + movl EFLAGS(%esp),%ecx # and this is cs.. + movl %eax,EFLAGS(%esp) # + movl %edx,EIP(%esp) # Now we move them to their "normal" places + movl %ecx,CS(%esp) # + movl %esp,%ebx + pushl %ebx + andl $-8192,%ebx # GET_CURRENT + movl exec_domain(%ebx),%edx # Get the execution domain + movl 4(%edx),%edx # Get the lcall7 handler for the domain + call *%edx + popl %eax + jmp ret_from_sys_call + + +#ifdef __SMP__ + ALIGN + .globl ret_from_smpfork +ret_from_smpfork: + GET_CURRENT(%ebx) + btrl $0, SYMBOL_NAME(scheduler_lock) + jmp ret_from_sys_call +#endif /* __SMP__ */ + +/* + * Return to user mode is not as complex as all this looks, + * but we want the default path for a system call return to + * go as quickly as possible which is why some of this is + * less clear than it otherwise should be. + */ + +ENTRY(system_call) + pushl %eax # save orig_eax + SAVE_ALL + GET_CURRENT(%ebx) + cmpl $(NR_syscalls),%eax + jae badsys + testb $0x20,flags(%ebx) # PF_TRACESYS + jne tracesys + call *SYMBOL_NAME(sys_call_table)(,%eax,4) + movl %eax,EAX(%esp) # save the return value + ALIGN + .globl ret_from_sys_call + .globl ret_from_intr +ret_from_sys_call: + movl SYMBOL_NAME(bh_mask),%eax + andl SYMBOL_NAME(bh_active),%eax + jne handle_bottom_half +ret_with_reschedule: + cmpl $0,need_resched(%ebx) + jne reschedule + cmpl $0,sigpending(%ebx) + jne signal_return + RESTORE_ALL + ALIGN +signal_return: + testl $(VM_MASK),EFLAGS(%esp) + pushl %esp + jne v86_signal_return + pushl $0 + call SYMBOL_NAME(do_signal) + addl $8,%esp + RESTORE_ALL + ALIGN +v86_signal_return: + call SYMBOL_NAME(save_v86_state) + movl %eax,%esp + pushl %eax + pushl $0 + call SYMBOL_NAME(do_signal) + addl $8,%esp + RESTORE_ALL + ALIGN +tracesys: + movl $-ENOSYS,EAX(%esp) + call SYMBOL_NAME(syscall_trace) + movl ORIG_EAX(%esp),%eax + call *SYMBOL_NAME(sys_call_table)(,%eax,4) + movl %eax,EAX(%esp) # save the return value + call SYMBOL_NAME(syscall_trace) + jmp ret_from_sys_call +badsys: + movl $-ENOSYS,EAX(%esp) + jmp ret_from_sys_call + + ALIGN +ret_from_exception: + movl SYMBOL_NAME(bh_mask),%eax + andl SYMBOL_NAME(bh_active),%eax + jne handle_bottom_half + ALIGN +ret_from_intr: + GET_CURRENT(%ebx) + movl EFLAGS(%esp),%eax # mix EFLAGS and CS + movb CS(%esp),%al + testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor? + jne ret_with_reschedule + RESTORE_ALL + + ALIGN +handle_bottom_half: + pushl $ret_from_intr + jmp SYMBOL_NAME(do_bottom_half) + + ALIGN +reschedule: + pushl $ret_from_sys_call + jmp SYMBOL_NAME(schedule) # test + + +ENTRY(divide_error) + pushl $0 # no error code + pushl $ SYMBOL_NAME(do_divide_error) + ALIGN +error_code: + pushl %ds + pushl %eax + xorl %eax,%eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + decl %eax # eax = -1 + pushl %ecx + pushl %ebx +#if 1 + xorl %ecx,%ecx # zero ecx + cld + mov %es,%cx # get the lower order bits of es +#else + cld +# Some older processors leave the top 16 bits of the 32 bit destination +# register undefined, rather than zeroed in the following instruction. +# This won't matter when restoring or loading a segment register from the +# stack. It may be a problem if any code reads the full 32 bit value. +# dosemu? kernel? Would somebody like to verify that this way is really OK? + movl %es,%cx +#endif + xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) + movl %esp,%edx + xchgl %ecx, ES(%esp) # get the address and save es. + pushl %eax # push the error code + pushl %edx + movl $(__KERNEL_DS),%edx + movl %dx,%ds + movl %dx,%es + GET_CURRENT(%ebx) + call *%ecx + addl $8,%esp + jmp ret_from_exception + +ENTRY(coprocessor_error) + pushl $0 + pushl $ SYMBOL_NAME(do_coprocessor_error) + jmp error_code + +ENTRY(device_not_available) + pushl $-1 # mark this as an int + SAVE_ALL + GET_CURRENT(%ebx) + pushl $ret_from_exception + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je SYMBOL_NAME(math_state_restore) + pushl $0 # temporary storage for ORIG_EIP + call SYMBOL_NAME(math_emulate) + addl $4,%esp + ret + +ENTRY(debug) + pushl $0 + pushl $ SYMBOL_NAME(do_debug) + jmp error_code + +ENTRY(nmi) + pushl $0 + pushl $ SYMBOL_NAME(do_nmi) + jmp error_code + +ENTRY(int3) + pushl $0 + pushl $ SYMBOL_NAME(do_int3) + jmp error_code + +ENTRY(overflow) + pushl $0 + pushl $ SYMBOL_NAME(do_overflow) + jmp error_code + +ENTRY(bounds) + pushl $0 + pushl $ SYMBOL_NAME(do_bounds) + jmp error_code + +ENTRY(invalid_op) + pushl $0 + pushl $ SYMBOL_NAME(do_invalid_op) + jmp error_code + +ENTRY(coprocessor_segment_overrun) + pushl $0 + pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun) + jmp error_code + +ENTRY(reserved) + pushl $0 + pushl $ SYMBOL_NAME(do_reserved) + jmp error_code + +ENTRY(double_fault) + pushl $ SYMBOL_NAME(do_double_fault) + jmp error_code + +ENTRY(invalid_TSS) + pushl $ SYMBOL_NAME(do_invalid_TSS) + jmp error_code + +ENTRY(segment_not_present) + pushl $ SYMBOL_NAME(do_segment_not_present) + jmp error_code + +ENTRY(stack_segment) + pushl $ SYMBOL_NAME(do_stack_segment) + jmp error_code + +ENTRY(general_protection) + pushl $ SYMBOL_NAME(do_general_protection) + jmp error_code + +ENTRY(alignment_check) + pushl $ SYMBOL_NAME(do_alignment_check) + jmp error_code + +ENTRY(page_fault) + pushl $ SYMBOL_NAME(do_page_fault) + jmp error_code + +ENTRY(spurious_interrupt_bug) + pushl $0 + pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) + jmp error_code + +.data +ENTRY(sys_call_table) + .long SYMBOL_NAME(sys_setup) /* 0 */ + .long SYMBOL_NAME(sys_exit) + .long SYMBOL_NAME(sys_fork) + .long SYMBOL_NAME(sys_read) + .long SYMBOL_NAME(sys_write) + .long SYMBOL_NAME(sys_open) /* 5 */ + .long SYMBOL_NAME(sys_close) + .long SYMBOL_NAME(sys_waitpid) + .long SYMBOL_NAME(sys_creat) + .long SYMBOL_NAME(sys_link) + .long SYMBOL_NAME(sys_unlink) /* 10 */ + .long SYMBOL_NAME(sys_execve) + .long SYMBOL_NAME(sys_chdir) + .long SYMBOL_NAME(sys_time) + .long SYMBOL_NAME(sys_mknod) + .long SYMBOL_NAME(sys_chmod) /* 15 */ + .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ + .long SYMBOL_NAME(sys_stat) + .long SYMBOL_NAME(sys_lseek) + .long SYMBOL_NAME(sys_getpid) /* 20 */ + .long SYMBOL_NAME(sys_mount) + .long SYMBOL_NAME(sys_umount) + .long SYMBOL_NAME(sys_setuid) + .long SYMBOL_NAME(sys_getuid) + .long SYMBOL_NAME(sys_stime) /* 25 */ + .long SYMBOL_NAME(sys_ptrace) + .long SYMBOL_NAME(sys_alarm) + .long SYMBOL_NAME(sys_fstat) + .long SYMBOL_NAME(sys_pause) + .long SYMBOL_NAME(sys_utime) /* 30 */ + .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ + .long SYMBOL_NAME(sys_access) + .long SYMBOL_NAME(sys_nice) + .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ + .long SYMBOL_NAME(sys_sync) + .long SYMBOL_NAME(sys_kill) + .long SYMBOL_NAME(sys_rename) + .long SYMBOL_NAME(sys_mkdir) + .long SYMBOL_NAME(sys_rmdir) /* 40 */ + .long SYMBOL_NAME(sys_dup) + .long SYMBOL_NAME(sys_pipe) + .long SYMBOL_NAME(sys_times) + .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ + .long SYMBOL_NAME(sys_brk) /* 45 */ + .long SYMBOL_NAME(sys_setgid) + .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_signal) + .long SYMBOL_NAME(sys_geteuid) + .long SYMBOL_NAME(sys_getegid) /* 50 */ + .long SYMBOL_NAME(sys_acct) + .long SYMBOL_NAME(sys_ni_syscall) /* old phys syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ + .long SYMBOL_NAME(sys_ioctl) + .long SYMBOL_NAME(sys_fcntl) /* 55 */ + .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ + .long SYMBOL_NAME(sys_setpgid) + .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ + .long SYMBOL_NAME(sys_olduname) + .long SYMBOL_NAME(sys_umask) /* 60 */ + .long SYMBOL_NAME(sys_chroot) + .long SYMBOL_NAME(sys_ustat) + .long SYMBOL_NAME(sys_dup2) + .long SYMBOL_NAME(sys_getppid) + .long SYMBOL_NAME(sys_getpgrp) /* 65 */ + .long SYMBOL_NAME(sys_setsid) + .long SYMBOL_NAME(sys_sigaction) + .long SYMBOL_NAME(sys_sgetmask) + .long SYMBOL_NAME(sys_ssetmask) + .long SYMBOL_NAME(sys_setreuid) /* 70 */ + .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_sigsuspend) + .long SYMBOL_NAME(sys_sigpending) + .long SYMBOL_NAME(sys_sethostname) + .long SYMBOL_NAME(sys_setrlimit) /* 75 */ + .long SYMBOL_NAME(sys_getrlimit) + .long SYMBOL_NAME(sys_getrusage) + .long SYMBOL_NAME(sys_gettimeofday) + .long SYMBOL_NAME(sys_settimeofday) + .long SYMBOL_NAME(sys_getgroups) /* 80 */ + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(old_select) + .long SYMBOL_NAME(sys_symlink) + .long SYMBOL_NAME(sys_lstat) + .long SYMBOL_NAME(sys_readlink) /* 85 */ + .long SYMBOL_NAME(sys_uselib) + .long SYMBOL_NAME(sys_swapon) + .long SYMBOL_NAME(sys_reboot) + .long SYMBOL_NAME(old_readdir) + .long SYMBOL_NAME(old_mmap) /* 90 */ + .long SYMBOL_NAME(sys_munmap) + .long SYMBOL_NAME(sys_truncate) + .long SYMBOL_NAME(sys_ftruncate) + .long SYMBOL_NAME(sys_fchmod) + .long SYMBOL_NAME(sys_fchown) /* 95 */ + .long SYMBOL_NAME(sys_getpriority) + .long SYMBOL_NAME(sys_setpriority) + .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ + .long SYMBOL_NAME(sys_statfs) + .long SYMBOL_NAME(sys_fstatfs) /* 100 */ + .long SYMBOL_NAME(sys_ioperm) + .long SYMBOL_NAME(sys_socketcall) + .long SYMBOL_NAME(sys_syslog) + .long SYMBOL_NAME(sys_setitimer) + .long SYMBOL_NAME(sys_getitimer) /* 105 */ + .long SYMBOL_NAME(sys_newstat) + .long SYMBOL_NAME(sys_newlstat) + .long SYMBOL_NAME(sys_newfstat) + .long SYMBOL_NAME(sys_uname) + .long SYMBOL_NAME(sys_iopl) /* 110 */ + .long SYMBOL_NAME(sys_vhangup) + .long SYMBOL_NAME(sys_idle) + .long SYMBOL_NAME(sys_vm86old) + .long SYMBOL_NAME(sys_wait4) + .long SYMBOL_NAME(sys_swapoff) /* 115 */ + .long SYMBOL_NAME(sys_sysinfo) + .long SYMBOL_NAME(sys_ipc) + .long SYMBOL_NAME(sys_fsync) + .long SYMBOL_NAME(sys_sigreturn) + .long SYMBOL_NAME(sys_clone) /* 120 */ + .long SYMBOL_NAME(sys_setdomainname) + .long SYMBOL_NAME(sys_newuname) + .long SYMBOL_NAME(sys_modify_ldt) + .long SYMBOL_NAME(sys_adjtimex) + .long SYMBOL_NAME(sys_mprotect) /* 125 */ + .long SYMBOL_NAME(sys_sigprocmask) + .long SYMBOL_NAME(sys_create_module) + .long SYMBOL_NAME(sys_init_module) + .long SYMBOL_NAME(sys_delete_module) + .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */ + .long SYMBOL_NAME(sys_quotactl) + .long SYMBOL_NAME(sys_getpgid) + .long SYMBOL_NAME(sys_fchdir) + .long SYMBOL_NAME(sys_bdflush) + .long SYMBOL_NAME(sys_sysfs) /* 135 */ + .long SYMBOL_NAME(sys_personality) + .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ + .long SYMBOL_NAME(sys_setfsuid) + .long SYMBOL_NAME(sys_setfsgid) + .long SYMBOL_NAME(sys_llseek) /* 140 */ + .long SYMBOL_NAME(sys_getdents) + .long SYMBOL_NAME(sys_select) + .long SYMBOL_NAME(sys_flock) + .long SYMBOL_NAME(sys_msync) + .long SYMBOL_NAME(sys_readv) /* 145 */ + .long SYMBOL_NAME(sys_writev) + .long SYMBOL_NAME(sys_getsid) + .long SYMBOL_NAME(sys_fdatasync) + .long SYMBOL_NAME(sys_sysctl) + .long SYMBOL_NAME(sys_mlock) /* 150 */ + .long SYMBOL_NAME(sys_munlock) + .long SYMBOL_NAME(sys_mlockall) + .long SYMBOL_NAME(sys_munlockall) + .long SYMBOL_NAME(sys_sched_setparam) + .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ + .long SYMBOL_NAME(sys_sched_setscheduler) + .long SYMBOL_NAME(sys_sched_getscheduler) + .long SYMBOL_NAME(sys_sched_yield) + .long SYMBOL_NAME(sys_sched_get_priority_max) + .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ + .long SYMBOL_NAME(sys_sched_rr_get_interval) + .long SYMBOL_NAME(sys_nanosleep) + .long SYMBOL_NAME(sys_mremap) + .long SYMBOL_NAME(sys_setresuid) + .long SYMBOL_NAME(sys_getresuid) /* 165 */ + .long SYMBOL_NAME(sys_vm86) + .long SYMBOL_NAME(sys_query_module) + .long SYMBOL_NAME(sys_poll) + .long SYMBOL_NAME(sys_nfsservctl) + .long SYMBOL_NAME(sys_setresgid) /* 170 */ + .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_prctl) + .long SYMBOL_NAME(sys_rt_sigreturn) + .long SYMBOL_NAME(sys_rt_sigaction) + .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ + .long SYMBOL_NAME(sys_rt_sigpending) + .long SYMBOL_NAME(sys_rt_sigtimedwait) + .long SYMBOL_NAME(sys_rt_sigqueueinfo) + .long SYMBOL_NAME(sys_rt_sigsuspend) + .long SYMBOL_NAME(sys_pread) /* 180 */ + .long SYMBOL_NAME(sys_pwrite) + .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_getcwd) + .long SYMBOL_NAME(sys_capget) + .long SYMBOL_NAME(sys_capset) /* 185 */ + .long SYMBOL_NAME(sys_sigaltstack) + .long SYMBOL_NAME(sys_sendfile) + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .long SYMBOL_NAME(sys_table) /* 190 */ + + .rept NR_syscalls-190 + .long SYMBOL_NAME(sys_ni_syscall) + .endr diff --git a/kernel/table21/main.c b/kernel/table21/main.c new file mode 100644 index 00000000..e6d1882b --- /dev/null +++ b/kernel/table21/main.c @@ -0,0 +1,61 @@ +/* + * linux/table/table_impl.c + * Copyright (C) 1998 Martin Baulig + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/tty.h> +#include <linux/user.h> +#include <linux/a.out.h> +#include <linux/string.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <linux/ioport.h> +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/swap.h> +#include <linux/slab.h> +#include <linux/smp.h> +#include <linux/signal.h> + +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/io.h> + +#include <linux/module.h> +#include <linux/table.h> + +#include "version.h" + +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); + +int (*table_function_ptr) (int, union table *, const void *) = 0; + +EXPORT_SYMBOL(table_function_ptr); + +EXPORT_SYMBOL(nr_running); +EXPORT_SYMBOL(pidhash); +EXPORT_SYMBOL(task); +EXPORT_SYMBOL(si_swapinfo); +EXPORT_SYMBOL(scheduling_functions_start_here); +EXPORT_SYMBOL(scheduling_functions_end_here); +EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(nr_tasks); +EXPORT_SYMBOL(last_pid); +EXPORT_SYMBOL(page_cache_size); +EXPORT_SYMBOL(init_mm); + +asmlinkage int +sys_table (int type, union table *buf, const void *param) +{ + if (table_function_ptr == 0) + return -ENOSYS; + + return (*table_function_ptr) (type, buf, param); +} diff --git a/kernel/table21/module.c b/kernel/table21/module.c new file mode 100644 index 00000000..1c1fa9c2 --- /dev/null +++ b/kernel/table21/module.c @@ -0,0 +1,607 @@ +/* + * linux/table/table_impl.c + * Copyright (C) 1998 Martin Baulig + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/tty.h> +#include <linux/user.h> +#include <linux/a.out.h> +#include <linux/string.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <linux/ioport.h> +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/swap.h> +#include <linux/slab.h> +#include <linux/smp.h> +#include <linux/signal.h> + +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/io.h> + +#include <linux/module.h> +#include <linux/table.h> + +#include "version.h" + +extern int (*table_function_ptr) (int, union table *, const void *); + +int table_fkt (int, union table *, const void *); + +EXPORT_NO_SYMBOLS; + +int +init_module(void) +{ + printk ("init_module () = %p - %d, %d\n", + table_fkt, sizeof (union table), sizeof (sigset_t)); + table_function_ptr = table_fkt; + return 0; +} + +void +cleanup_module(void) +{ + table_function_ptr = 0; +} + +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + +#ifdef CONFIG_DEBUG_MALLOC +int get_malloc(char * buffer); +#endif + +static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, + sigset_t *catch) +{ + struct k_sigaction *k; + int i; + + sigemptyset(ign); + sigemptyset(catch); + +#if 0 + printk ("collect_sigign_sigcatch: %p - %p\n", + p, p->sig); +#endif + + if (p->sig) { + k = p->sig->action; + for (i = 1; i <= _NSIG; ++i, ++k) { +#if 0 + printk ("signal: %d - %p (%p, %p)\n", + i, k->sa.sa_handler, SIG_IGN, SIG_DFL); +#endif + if (k->sa.sa_handler == SIG_IGN) + sigaddset(ign, i); + else if (k->sa.sa_handler != SIG_DFL) + sigaddset(catch, i); + } + } +} + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static unsigned long get_wchan(struct task_struct *p) +{ + if (!p || p == current || p->state == TASK_RUNNING) + return 0; +#if defined(__i386__) + { + unsigned long ebp, eip; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + if (!stack_page) + return 0; + ebp = p->tss.ebp; + do { + if (ebp < stack_page || ebp >= 4092+stack_page) + return 0; + eip = *(unsigned long *) (ebp+4); + if (eip < first_sched || eip >= last_sched) + return eip; + ebp = *(unsigned long *) ebp; + } while (count++ < 16); + } +#elif defined(__alpha__) + /* + * This one depends on the frame size of schedule(). Do a + * "disass schedule" in gdb to find the frame size. Also, the + * code assumes that sleep_on() follows immediately after + * interruptible_sleep_on() and that add_timer() follows + * immediately after interruptible_sleep(). Ugly, isn't it? + * Maybe adding a wchan field to task_struct would be better, + * after all... + */ + { + unsigned long schedule_frame; + unsigned long pc; + + pc = thread_saved_pc(&p->tss); + if (pc >= first_sched && pc < last_sched) { + schedule_frame = ((unsigned long *)p->tss.ksp)[6]; + return ((unsigned long *)schedule_frame)[12]; + } + return pc; + } +#elif defined(__mc68000__) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + extern int sys_pause (void); + + stack_page = p->kernel_stack_page; + if (!stack_page) + return 0; + fp = ((struct switch_stack *)p->tss.ksp)->a6; + do { + if (fp < stack_page || fp >= 4088+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (pc < first_sched || pc >= last_sched) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); + } +#elif defined(__powerpc__) + return (p->tss.wchan); +#elif defined (CONFIG_ARM) + { + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp (&p->tss); + do { + if (fp < stack_page || fp > 4092+stack_page) + return 0; + lr = pc_pointer (((unsigned long *)fp)[-1]); + if (lr < first_sched || lr > last_sched) + return lr; + fp = *(unsigned long *) (fp - 12); + } while (count ++ < 16); + } +#endif + return 0; +} + +#if defined(__i386__) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +#elif defined(__alpha__) + /* + * See arch/alpha/kernel/ptrace.c for details. + */ +# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + + (long)&((struct pt_regs *)0)->reg) +# define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) +# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(CONFIG_ARM) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) +#elif defined(__mc68000__) +#define KSTK_EIP(tsk) \ + ({ \ + unsigned long eip = 0; \ + if ((tsk)->tss.esp0 > PAGE_SIZE && \ + MAP_NR((tsk)->tss.esp0) < max_mapnr) \ + eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \ + eip; }) +#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(__powerpc__) +#define KSTK_EIP(tsk) ((tsk)->tss.regs->nip) +#define KSTK_ESP(tsk) ((tsk)->tss.regs->gpr[1]) +#elif defined (__sparc_v9__) +# define KSTK_EIP(tsk) ((tsk)->tss.kregs->tpc) +# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP]) +#elif defined(__sparc__) +# define KSTK_EIP(tsk) ((tsk)->tss.kregs->pc) +# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP]) +#endif + +/* Gcc optimizes away "strlen(x)" for constant x */ +#define ADDBUF(buffer, string) \ +do { memcpy(buffer, string, strlen(string)); \ + buffer += strlen(string); } while (0) + +static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pte_t * pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd)); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t page = *pte; + + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + ++*total; + if (!pte_present(page)) + continue; + ++*pages; + if (pte_dirty(page)) + ++*dirty; + if (MAP_NR(pte_page(page)) >= max_mapnr) + continue; + if (atomic_read(&mem_map[MAP_NR(pte_page(page))].count) > 1) + ++*shared; + } while (address < end); +} + +static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pmd_t * pmd; + unsigned long end; + + if (pgd_none(*pgd)) + return; + if (pgd_bad(*pgd)) { + printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd)); + pgd_clear(pgd); + return; + } + pmd = pmd_offset(pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + statm_pte_range(pmd, address, end - address, pages, shared, dirty, total); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end, + int * pages, int * shared, int * dirty, int * total) +{ + while (address < end) { + statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + pgd++; + } +} + +int +table_fkt (int type, union table *buf, const void *param) +{ + union table tbl; + struct sysinfo i; + struct task_struct *tsk = NULL; + struct proclist_args plistargs; + int index, tindex, err, tty; + sigset_t sigign, sigcatch; + pid_t pid; + + if (type == TABLE_VERSION) + return _TABLE_VERSION; + + if (!buf) + return -EFAULT; + + memset (&tbl, 0, sizeof (union table)); + + /* For TABLE_PROC_*, read pid and get task_struct */ + + switch (type) { + case TABLE_PROC_UID: + case TABLE_PROC_MEM: + case TABLE_PROC_SEGMENT: + case TABLE_PROC_TIME: + case TABLE_PROC_STATE: + case TABLE_PROC_SIGNAL: + case TABLE_PROC_KERNEL: + err = verify_area (VERIFY_READ, param, sizeof (pid_t)); + if (err) + return err; + copy_from_user (&pid, param, sizeof (pid_t)); + + read_lock (&tasklist_lock); + tsk = find_task_by_pid (pid); + /* FIXME!! This should be done after the last use */ + read_unlock(&tasklist_lock); + + if (tsk == NULL) + return -ESRCH; + break; + case TABLE_PROCLIST: + err = verify_area (VERIFY_READ, param, + sizeof (struct proclist_args)); + if (err) + return err; + copy_from_user (&plistargs, param, + sizeof (struct proclist_args)); + break; + } + + /* Main function dispatcher */ + + switch (type) { + case TABLE_PROCLIST: + tsk = task [0]; + read_lock (&tasklist_lock); + for (index = tindex = 0; index < nr_tasks; + index++, tsk = tsk->next_task) { + if (tsk->pid == 0) continue; + switch (plistargs.which & TABLE_KERN_PROC_MASK) { + case TABLE_KERN_PROC_PID: + if (tsk->pid != plistargs.arg) continue; + break; + case TABLE_KERN_PROC_PGRP: + if (tsk->pgrp != plistargs.arg) continue; + break; + case TABLE_KERN_PROC_SESSION: + if (tsk->session != plistargs.arg) continue; + case TABLE_KERN_PROC_TTY: + tty = tsk->tty ? + kdev_t_to_nr (tsk->tty->device) : 0; + if (tty != plistargs.arg) continue; + break; + case TABLE_KERN_PROC_UID: + if (tsk->uid != plistargs.arg) continue; + break; + case TABLE_KERN_PROC_RUID: + if (tsk->euid != plistargs.arg) continue; + break; + } + + if ((plistargs.which & TABLE_EXCLUDE_IDLE) && + (tsk->state != 0)) + continue; + + if ((plistargs.which & TABLE_EXCLUDE_NOTTY) && + (tsk->tty == NULL)) + continue; + + tbl.proclist.pids [tindex++] = tsk->pid; + } + tbl.proclist.nr_running = nr_running; + tbl.proclist.last_pid = last_pid; + tbl.proclist.nr_tasks = tindex; + read_unlock(&tasklist_lock); + break; + case TABLE_CPU: + tbl.cpu.total = jiffies; + tbl.cpu.user = kstat.cpu_user; + tbl.cpu.nice = kstat.cpu_nice; + tbl.cpu.sys = kstat.cpu_system; + tbl.cpu.idle = tbl.cpu.total - + (tbl.cpu.user + tbl.cpu.nice + tbl.cpu.sys); + tbl.cpu.frequency = HZ; + break; + case TABLE_MEM: + si_meminfo (&i); + tbl.mem.total = i.totalram; + tbl.mem.used = i.totalram - i.freeram; + tbl.mem.free = i.freeram; + tbl.mem.shared = i.sharedram; + tbl.mem.buffer = i.bufferram; + tbl.mem.cached = page_cache_size << PAGE_SHIFT; + break; + case TABLE_SWAP: + si_swapinfo (&i); + tbl.swap.total = i.totalswap; + tbl.swap.used = i.totalswap - i.freeswap; + tbl.swap.free = i.freeswap; + break; + case TABLE_LOADAVG: + tbl.loadavg.loadavg [0] = (double) avenrun [0] / (1 << FSHIFT); + tbl.loadavg.loadavg [1] = (double) avenrun [1] / (1 << FSHIFT); + tbl.loadavg.loadavg [2] = (double) avenrun [2] / (1 << FSHIFT); + tbl.loadavg.nr_running = nr_running; + tbl.loadavg.nr_tasks = nr_tasks; + tbl.loadavg.last_pid = last_pid; + break; + case TABLE_UPTIME: + tbl.uptime.uptime = jiffies; + tbl.uptime.idle = task[0]->times.tms_utime + + task[0]->times.tms_stime; + break; + case TABLE_PROC_STATE: + tbl.proc_state.uid = tsk->uid; + tbl.proc_state.gid = tsk->gid; + tbl.proc_state.state = tsk->state; + tbl.proc_state.flags = tsk->flags; + memcpy (tbl.proc_state.comm, tsk->comm, + sizeof (tbl.proc_state.comm)); + break; + case TABLE_PROC_UID: + tbl.proc_uid.uid = tsk->uid; + tbl.proc_uid.euid = tsk->euid; + tbl.proc_uid.suid = tsk->suid; + tbl.proc_uid.fsuid = tsk->fsuid; + + tbl.proc_uid.gid = tsk->gid; + tbl.proc_uid.egid = tsk->egid; + tbl.proc_uid.sgid = tsk->sgid; + tbl.proc_uid.fsgid = tsk->fsgid; + + tbl.proc_uid.pid = tsk->pid; + tbl.proc_uid.pgrp = tsk->pgrp; + tbl.proc_uid.ppid = tsk->p_pptr->pid; + + tbl.proc_uid.session = tsk->session; + tbl.proc_uid.tty = tsk->tty ? + kdev_t_to_nr (tsk->tty->device) : 0; + tbl.proc_uid.tpgid = tsk->tty ? tsk->tty->pgrp : -1; + + tbl.proc_uid.priority = tsk->priority; + tbl.proc_uid.counter = tsk->counter; + tbl.proc_uid.def_priority = DEF_PRIORITY; + break; + case TABLE_PROC_SIGNAL: + memcpy (&tbl.proc_signal.signal, &tsk->signal, + sizeof (tbl.proc_signal.signal)); + + memcpy (&tbl.proc_signal.blocked, &tsk->blocked, + sizeof (tbl.proc_signal.blocked)); + + collect_sigign_sigcatch (tsk, &sigign, &sigcatch); + + memcpy (&tbl.proc_signal.ignored, &sigign, + sizeof (tbl.proc_signal.ignored)); + + memcpy (&tbl.proc_signal.caught, &sigcatch, + sizeof (tbl.proc_signal.caught)); + +#if 0 + printk ("PROC_SIGNAL: (%lu, %lu) - (%lu, %lu)\n", + tbl.proc_signal.ignored.sig [0], + tbl.proc_signal.ignored.sig [1], + tbl.proc_signal.caught.sig [0], + tbl.proc_signal.caught.sig [1]); +#endif + break; + case TABLE_PROC_MEM: + if (tsk->mm && tsk->mm != &init_mm) { + tbl.proc_mem.context = tsk->mm->context; + tbl.proc_mem.start_code = tsk->mm->start_code; + tbl.proc_mem.end_code = tsk->mm->end_code; + tbl.proc_mem.start_data = tsk->mm-> start_data; + tbl.proc_mem.end_data = tsk->mm->end_data; + tbl.proc_mem.start_brk = tsk->mm->start_brk; + tbl.proc_mem.brk = tsk->mm->brk; + tbl.proc_mem.start_stack = tsk->mm->start_stack; + tbl.proc_mem.start_mmap = tsk->mm->mmap ? + tsk->mm->mmap->vm_start : 0; + tbl.proc_mem.arg_start = tsk->mm->arg_start; + tbl.proc_mem.arg_end = tsk->mm->arg_end; + tbl.proc_mem.env_start = tsk->mm->env_start; + tbl.proc_mem.env_end = tsk->mm->env_end; + tbl.proc_mem.rss = tsk->mm->rss << PAGE_SHIFT; + tbl.proc_mem.total_vm = tsk->mm->total_vm; + tbl.proc_mem.locked_vm = tsk->mm->locked_vm; + } + tbl.proc_mem.rlim = tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0; + break; + case TABLE_PROC_SEGMENT: + if (tsk->mm && tsk->mm != &init_mm) { + unsigned long vsize = 0; + int size = 0, resident = 0, share = 0; + int trs = 0, lrs = 0, drs = 0, srs = 0, dt = 0; + struct vm_area_struct * vma = tsk->mm->mmap; + + while (vma) { + pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start); + int pages = 0, shared = 0, dirty = 0, total = 0; + + vsize += vma->vm_end - vma->vm_start; + + statm_pgd_range (pgd, vma->vm_start, vma->vm_end, + + &pages, &shared, &dirty, &total); + + resident += pages; + share += shared; + dt += dirty; + size += total; + + /* Well, shared library seem to get mapped + * above 0x40000000 and are executable, + * so I use this hack to get their size. + */ + + if (vma->vm_flags & VM_GROWSDOWN) + srs += pages; /* stack */ + else if ((vma->vm_flags & VM_EXEC) && + (vma->vm_start > 0x40000000)) + lrs += pages; /* library */ + else if (vma->vm_flags & VM_EXECUTABLE) + trs += pages; /* text */ + else + drs += pages; + + vma = vma->vm_next; + } + + tbl.proc_segment.vsize = vsize; + tbl.proc_segment.size = size << PAGE_SHIFT; + tbl.proc_segment.resident = resident << PAGE_SHIFT; + tbl.proc_segment.shared = share << PAGE_SHIFT; + tbl.proc_segment.trs = trs << PAGE_SHIFT; + tbl.proc_segment.lrs = lrs << PAGE_SHIFT; + tbl.proc_segment.drs = drs << PAGE_SHIFT; + tbl.proc_segment.srs = srs << PAGE_SHIFT; + tbl.proc_segment.dt = dt << PAGE_SHIFT; + } + break; + case TABLE_PROC_TIME: + tbl.proc_time.utime = tsk->times.tms_utime; + tbl.proc_time.stime = tsk->times.tms_stime; + tbl.proc_time.cutime = tsk->times.tms_cutime; + tbl.proc_time.cstime = tsk->times.tms_cstime; + + tbl.proc_time.start_time = tsk->start_time; + tbl.proc_time.timeout = tsk->timeout; + tbl.proc_time.policy = tsk->policy; + tbl.proc_time.rt_priority = tsk->rt_priority; + + tbl.proc_time.it_real_value = tsk->it_real_value; + tbl.proc_time.it_prof_value = tsk->it_prof_value; + tbl.proc_time.it_virt_value = tsk->it_virt_value; + tbl.proc_time.it_real_incr = tsk->it_real_incr; + tbl.proc_time.it_prof_incr = tsk->it_prof_incr; + tbl.proc_time.it_virt_incr = tsk->it_virt_incr; + break; + case TABLE_PROC_KERNEL: + tbl.proc_kernel.min_flt = tsk->min_flt; + tbl.proc_kernel.cmin_flt = tsk->cmin_flt; + tbl.proc_kernel.maj_flt = tsk->maj_flt; + tbl.proc_kernel.cmaj_flt = tsk->cmaj_flt; + + tbl.proc_kernel.kesp = KSTK_ESP(tsk); + tbl.proc_kernel.keip = KSTK_EIP(tsk); + + tbl.proc_kernel.nswap = tsk->nswap; + tbl.proc_kernel.cnswap = tsk->cnswap; + + tbl.proc_kernel.wchan = get_wchan (tsk); + break; + default: + return -EINVAL; + } + + err = verify_area (VERIFY_WRITE, buf, sizeof (struct table)); + if (err) + return err; + + copy_to_user (buf, &tbl, sizeof (union table)); + + return 0; +} diff --git a/kernel/table21/unistd-i386.h b/kernel/table21/unistd-i386.h new file mode 100644 index 00000000..a7c30c83 --- /dev/null +++ b/kernel/table21/unistd-i386.h @@ -0,0 +1,344 @@ +#ifndef _ASM_I386_UNISTD_H_ +#define _ASM_I386_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_setup 0 /* used only by init, to get system going */ +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_phys 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_profil 98 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86old 113 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_modify_ldt 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_vm86 166 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread 180 +#define __NR_pwrite 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_streams1 188 /* some people actually want it */ +#define __NR_streams2 189 /* some people actually want it */ +#define __NR_table 190 + +/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */ + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + errno = -(res); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define _syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +__syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +__syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ +__syscall_return(type,__res); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +__syscall_return(type,__res); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +__syscall_return(type,__res); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +__syscall_return(type,__res); \ +} + +#ifdef __KERNEL_SYSCALLS__ + +/* + * we need this inline - forking from kernel space will result + * in NO COPY ON WRITE (!!!), until an execve is executed. This + * is no problem, but for the stack. This is handled by not letting + * main() use the stack at all after fork(). Thus, no function + * calls - which means inline code for fork too, as otherwise we + * would use the stack upon exit from 'fork()'. + * + * Actually only pause and fork are needed inline, so that there + * won't be any messing with the stack from main(), but we define + * some others too. + */ +#define __NR__exit __NR_exit +static inline _syscall0(int,idle) +static inline _syscall0(int,pause) +static inline _syscall1(int,setup,int,magic) +static inline _syscall0(int,sync) +static inline _syscall0(pid_t,setsid) +static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) +static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) +static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) +static inline _syscall1(int,dup,int,fd) +static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) +static inline _syscall3(int,open,const char *,file,int,flag,int,mode) +static inline _syscall1(int,close,int,fd) +static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) +static inline _syscall1(int,delete_module,const char *,name) + +static inline pid_t wait(int * wait_stat) +{ + return waitpid(-1,wait_stat,0); +} + +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be free'd until both the parent and the child have exited. + */ +static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + "movl %%esp,%%esi\n\t" + "int $0x80\n\t" /* Linux/i386 system call */ + "cmpl %%esp,%%esi\n\t" /* child or parent? */ + "je 1f\n\t" /* parent - jump */ + "pushl %3\n\t" /* push argument */ + "call *%4\n\t" /* call fn */ + "movl %2,%0\n\t" /* exit */ + "int $0x80\n" + "1:\t" + :"=a" (retval) + :"0" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "b" (flags | CLONE_VM) + :"si"); + return retval; +} + +#endif + +#endif /* _ASM_I386_UNISTD_H_ */ diff --git a/kernel/table21/version.h b/kernel/table21/version.h new file mode 100644 index 00000000..d47411ee --- /dev/null +++ b/kernel/table21/version.h @@ -0,0 +1 @@ +#define _TABLE_VERSION 1 diff --git a/kernel/version.h b/kernel/version.h new file mode 100644 index 00000000..d47411ee --- /dev/null +++ b/kernel/version.h @@ -0,0 +1 @@ +#define _TABLE_VERSION 1 |