All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [parisc-linux] A few questions
From: Thibaut VARENE @ 2002-10-27  2:54 UTC (permalink / raw)
  To: posix; +Cc: parisc-linux
In-Reply-To: <000901c27d25$c18647a0$0100a8c0@posix2paebsbtq>

-------------------
> Hi!
> I was wondering if there is another way than what is descriped in 
the PA-RISC/linux-bootHOWTO to exit serial console and enter graphics 
console?
> 
> I would really appreciate an answer //Patrick

I confess not even understanding the meaning of this question.

You don't "enter" or "exit" serial/graphic console.
You switch from one too another.

There is only one way to do so, the one described in the howto.
If there were others, we would have mentionned them...

HTH,


Thibaut VARENE
PA/Linux ESIEE Team
http://pateam.esiee.fr/

^ permalink raw reply

* Re: Linux 2.5.44-ac4
From: Dieter Nützel @ 2002-10-27  2:58 UTC (permalink / raw)
  To: Linux Kernel List; +Cc: Alan Cox, Patrick Mochel

radeon.o and sg.o NOT removable.

Module                  Size  Used by    Not tainted
sg                         0   0  (deleted)

Badness in put_device at drivers/base/core.c:139

void put_device(struct device * dev)
{
        down(&device_sem);
        if (!atomic_dec_and_test(&dev->refcount)) {
                up(&device_sem);
                return;
        }
        list_del_init(&dev->node);
        list_del_init(&dev->g_list);
        up(&device_sem);

>>>        WARN_ON(dev->state == DEVICE_REGISTERED);

        if (dev->state == DEVICE_GONE)
                device_del(dev);
}


ksymoops 2.4.7 on i686 2.5.44-ac4.  Options used
     -V (default)
     -k /proc/ksyms (default)
     -l /proc/modules (default)
     -o /lib/modules/2.5.44-ac4/ (default)
     -m /boot/System.map (specified)

Warning (compare_ksyms_lsmod): module sg is in lsmod but not in ksyms, 
probably no symbols exported
Call Trace: [<c01c1392>]  [<fd4fbe9a>]  [<fd50075c>]  [<fd50076c>]  
[<fd500640>]  [<c01e1f2c>]  [<fd4fbf2f>]  [<fd500640>]  [<c011f02c>]  
[<c011e358>]  [<c010754f>]
Call Trace: [<c01c1392>]  [<fd4fbe9a>]  [<fd50075c>]  [<fd50076c>]  
[<fd500640>]  [<c01e36ba>]  [<c01e1f2c>]  [<fd4fbf2f>]  [<fd500640>]  
[<c011f02c>]  [<c011e358>]  [<c010754f>]
Call Trace: [<c01c1392>]  [<fd4fbe9a>]  [<fd50075c>]  [<fd50076c>]  
[<fd500640>]  [<c01e36ba>]  [<c01e1f2c>]  [<fd4fbf2f>]  [<fd500640>]  
[<c011f02c>]  [<c011e358>]  [<c010754f>]
Call Trace: [<c01c1392>]  [<fd4fbe9a>]  [<fd50075c>]  [<fd50076c>]  
[<fd500640>]  [<c01e36ba>]  [<c01e1f2c>]  [<fd4fbf2f>]  [<fd500640>]  
[<c011f02c>]  [<c011e358>]  [<c010754f>]
Call Trace: [<c01c1392>]  [<fd4fbe9a>]  [<fd50075c>]  [<fd50076c>]  
[<fd500640>]  [<c01e1f2c>]  [<fd4fbf2f>]  [<fd500640>]  [<c011f02c>]  
[<c011e358>]  [<c010754f>]
Unable to handle kernel paging request at virtual address f90fa03c
c01c1e7d
*pde = 30a3f067
Oops: 0000
CPU:    1
EIP:    0060:[<c01c1e7d>]    Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00210246
eax: fd5006b0   ebx: c02c0820   ecx: fd500698   edx: f90fa03c
esi: fd500688   edi: fd500688   ebp: 00000000   esp: dfe6ff4c
ds: 0068   es: 0068   ss: 0068
Stack: c02c0820 fd500688 c02c0824 c01c20cb fd500688 fd500688 c02c0820 00000001
       c01c2596 fd500688 fd500688 fd4f9000 c01c2669 fd500688 fd4f9000 fd4fbf73
       fd500688 c011f02c dfe6e000 fd4f9000 f90f6000 c011e358 fd4f9000 00000001
Call Trace: [<fd500688>]  [<c01c20cb>]  [<fd500688>]  [<fd500688>]  
[<c01c2596>]  [<fd500688>]  [<fd500688>]  [<c01c2669>]  [<fd500688>]  
[<fd4fbf73>]  [<fd500688>]  [<c011f02c>]  [<c011e358>]  [<c010754f>]
Code: 8b 32 39 c2 74 2b 8d 5a e8 53 e8 e4 f3 ff ff 83 c4 04 85 c0


Trace; c01c1392 <put_device+a2/c0>
Trace; fd4fbe9a <[radeon].data.end+439107b/43b81e1>
Trace; fd50075c <[radeon].data.end+439593d/43b81e1>
Trace; fd50076c <[radeon].data.end+439594d/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c01e1f2c <scsi_unregister_device+5c/170>
Trace; fd4fbf2f <[radeon].data.end+4391110/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>
Trace; c01c1392 <put_device+a2/c0>
Trace; fd4fbe9a <[radeon].data.end+439107b/43b81e1>
Trace; fd50075c <[radeon].data.end+439593d/43b81e1>
Trace; fd50076c <[radeon].data.end+439594d/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c01e36ba <scsi_host_get_next+5a/70>
Trace; c01e1f2c <scsi_unregister_device+5c/170>
Trace; fd4fbf2f <[radeon].data.end+4391110/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>
Trace; c01c1392 <put_device+a2/c0>
Trace; fd4fbe9a <[radeon].data.end+439107b/43b81e1>
Trace; fd50075c <[radeon].data.end+439593d/43b81e1>
Trace; fd50076c <[radeon].data.end+439594d/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c01e36ba <scsi_host_get_next+5a/70>
Trace; c01e1f2c <scsi_unregister_device+5c/170>
Trace; fd4fbf2f <[radeon].data.end+4391110/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>
Trace; c01c1392 <put_device+a2/c0>
Trace; fd4fbe9a <[radeon].data.end+439107b/43b81e1>
Trace; fd50075c <[radeon].data.end+439593d/43b81e1>
Trace; fd50076c <[radeon].data.end+439594d/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c01e36ba <scsi_host_get_next+5a/70>
Trace; c01e1f2c <scsi_unregister_device+5c/170>
Trace; fd4fbf2f <[radeon].data.end+4391110/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>
Trace; c01c1392 <put_device+a2/c0>
Trace; fd4fbe9a <[radeon].data.end+439107b/43b81e1>
Trace; fd50075c <[radeon].data.end+439593d/43b81e1>
Trace; fd50076c <[radeon].data.end+439594d/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c01e1f2c <scsi_unregister_device+5c/170>
Trace; fd4fbf2f <[radeon].data.end+4391110/43b81e1>
Trace; fd500640 <[radeon].data.end+4395821/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>

>>EIP; c01c1e7d <driver_detach+d/50>   <=====

>>eax; fd5006b0 <[radeon].data.end+4395891/43b81e1>
>>ebx; c02c0820 <scsi_driverfs_bus_type+0/80>
>>ecx; fd500698 <[radeon].data.end+4395879/43b81e1>
>>edx; f90fa03c <[pppoe].data.end+1b9d/6b61>
>>esi; fd500688 <[radeon].data.end+4395869/43b81e1>
>>edi; fd500688 <[radeon].data.end+4395869/43b81e1>
>>esp; dfe6ff4c <_end+1fafb01c/38cb90d0>

Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; c01c20cb <bus_remove_driver+3b/80>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; c01c2596 <put_driver+56/80>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; c01c2669 <driver_unregister+49/4e>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; fd4fbf73 <[radeon].data.end+4391154/43b81e1>
Trace; fd500688 <[radeon].data.end+4395869/43b81e1>
Trace; c011f02c <free_module+1c/f0>
Trace; c011e358 <sys_delete_module+248/2f0>
Trace; c010754f <syscall_call+7/b>

Code;  c01c1e7d <driver_detach+d/50>
00000000 <_EIP>:
Code;  c01c1e7d <driver_detach+d/50>   <=====
   0:   8b 32                     mov    (%edx),%esi   <=====
Code;  c01c1e7f <driver_detach+f/50>
   2:   39 c2                     cmp    %eax,%edx
Code;  c01c1e81 <driver_detach+11/50>
   4:   74 2b                     je     31 <_EIP+0x31> c01c1eae 
<driver_detach+3e/50>
Code;  c01c1e83 <driver_detach+13/50>
   6:   8d 5a e8                  lea    0xffffffe8(%edx),%ebx
Code;  c01c1e86 <driver_detach+16/50>
   9:   53                        push   %ebx
Code;  c01c1e87 <driver_detach+17/50>
   a:   e8 e4 f3 ff ff            call   fffff3f3 <_EIP+0xfffff3f3> c01c1270 
<get_device+0/80>
Code;  c01c1e8c <driver_detach+1c/50>
   f:   83 c4 04                  add    $0x4,%esp
Code;  c01c1e8f <driver_detach+1f/50>
  12:   85 c0                     test   %eax,%eax

Regards,
	Dieter

^ permalink raw reply

* [LARTC] Thanks Werner :)
From: Folke Aeon @ 2002-10-27  2:51 UTC (permalink / raw)
  To: lartc

Thanks Werner :)

  you help means a lot to me. :)

folke.



>From: Werner Almesberger <wa@almesberger.net>
>To: Folke Aeon <aeon_folke@hotmail.com>
>CC: Subject: Re: [LARTC] can anyone help me to solve this problem?
>Date: Sat, 26 Oct 2002 13:49:44 -0300
>
>Folke Aeon wrote:
> > it works currently, but wonder whether there will be
> > any negative influence or not. would you please give
> > some comment on this ?
>
>It should work. You just have to be aware that your kernel
>is doing some odd things ...
>
> > another thing, i noticed that since the dsmark dequeue
> > function does not support mpls protocol, so when a mpls
> > packet arrives, it complains "unsupported protocol".
>
>Only if you try to change the DS field.
>
> > Although the tcindex value is still there, it just cannot
> > use it . i think this is where the problem lies in.
>
>No. tc_index does not have to equal the DSCP or DS field.
>In dsmark, tc_index is an index to a table with DS field
>changes. All you need to do is to reserve a tc_index value
>for non-IP traffic, and only mark IP traffic with other
>values than that.
>
>- Werner
>


_________________________________________________________________
Surf the Web without missing calls! Get MSN Broadband. 
http://resourcecenter.msn.com/access/plans/freeactivation.asp

_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/

^ permalink raw reply

* [PATCH][RFC] x86 multiple user-mode privilege rings
From: Luca Barbieri @ 2002-10-27  2:48 UTC (permalink / raw)
  To: Linux-Kernel ML

[-- Attachment #1: Type: text/plain, Size: 79299 bytes --]

Short explaination: 
This patch implements a feature called "x86 multiring", which is a
shorthand for x86 multiple user-mode privilege rings support. 
It allows user-mode programs to create DPL 1 and 2 segments and get a
modifiable per-process copy of IDT. 

User Mode Linux can use these features to implement a syscall mechanism
identical to the one used by the kernel-mode kernel, and thus much
faster than the current one, with free memory protection and with zero
context switches. 

Wine could also use it to achieve fast syscall-level emulation of
Windows NT (and, to a lesser extent, Windows 3.1 and 9x). 

Obviously there is some risk of the patch creating security holes. 


System calls:
All operations are performed using the new sys_multiring syscall. The
API is documented in include/asm-i386/multiring.h, that multiring
applications should include. 


Supervisor problems: 
The most serious issue caused by the use of ring 1 and 2 is that they
are intended for kernel code, which means that they count as supervisor
wherever a "user/supervisor" bit is present. 

This results in: 
- Unavailaibility of multiring on 386 processors since they don't
support supervisor WP. 

- Page protection no longer working 
While this may seem catastrophic, it isn't because segment-level
protection can be used instead. 
To enforce it, the patch modifies the GDT so that the default CS and DS
have a limit at __PAGE_OFFSET - 1. 
LDT and TLS interfaces are also changed to alter segment limits to avoid
overlap with the kernel area. If this is impossible, multiring mode is
inhibited using bad_segments mm_context_t field; if the process is
already in multiring mode the operation fails.
vsyscalls will need to be put before the rest of the kernel with this
scheme.

- Supervisor bit in error code in page faults not reliable (regs->xcs is
used instead, with the only problem of not being able to tell f00f
invalid opcodes from page faults) 

- Potential minor problems for profilers since to get DPL 1/2 events,
DPL 0 events also have to be enabled. 

Based on my reading of Intel manuals, there should not be any other
problem, but I might have missed something.


IDT functionality: 
When multiring mode is entered, the default IDT is copied to a new
allocated page and a pointer to the new one is stored in mm_context_t. 
The initial multiring IDT is identical to the default one, with the
exception of the SYSCALL_VECTOR DPL which is set to 1. 
The code includes a config option to put IDTs in high memory, that is
however untested and not very useful anyway. 

IDTs are loaded in two different ways: if CONFIG_X86_HIGHIDT is set or
the processor is f00f-buggy, each CPU gets a fixmap entry that is
remapped to load another IDT; otherwise, a simple lidt instruction is
used. 

sys_multiring allows to read, copy and set gates in the IDT. 
The vectors that are settable are currently 0x20-0x2f (because DOS and
Windows are here), 0x80 and 0xf1-0xfa. 
Set operations will fail if the user tries to set a gate to a kernel
mode address which isn't the syscall one or a task or interrupt gate. 
The i8259 is remapped to 0x30-0x3f to accomodate this. 

The multiring_mode filed is added to the thread structure, and is 1 if
the thread has entered multiring mode (i.e. selectors are RPL 1-ed).


GDT functionality: 
When switching to a multiring mm, the DPL in the default user CS and DS
is set to 1, to prevent ring 2 and 3 to load them and thus bypass any
security that the DPL 1 code might be enforcing. 


LDT/TLS functionality: 
When in multiring mode, LDT/TLS functions honor the new dpl field in
struct user_desc that of course allows to set a custom dpl in the
descriptors. 
They are also changed to support segment-level protection as outlined
above. 


TSS functionality: 
sys_multiring allows to modify the ring 1 and 2 TSS ESP and SS that are
loaded on inter-privilege call. 
The values are kept in the thread structure and are loaded on task
switch. 


clone functionality: 
The CLONE_IDT flag is added, and does the obvious thing. Note that if
the task is not in multiring mode, it is silently ignored. 
The CLONE_CLEAR_IDT flag is also added and also does the obvious thing
and takes precedence over CLONE_IDT.


Entering multiring mode: 
Multiring mode can be entered using sys_multiring(MULTIRING_ELEVATE). 
This will allocate a new IDT, fix the GDT and put RPL 1 selectors in
cs/ds/es/ss/fs/gs. Note that all other threads will also get RPL 1
selectors.
RPL 1 selectors are loaded only if the selector points to the default CS
or DS.


Limitations: 
- Since there are only 4 privilege rings only up to 2 UMLs can be nested
- Doesn't work on 386 


Potential improvements: 
- Copy on write IDTs 
- Reduction of IDT allocation size from 4 KB to 2 KB 
- x86-64? 


Diffstat:
 arch/i386/Config.help                |    7 
 arch/i386/config.in                  |    1 
 arch/i386/kernel/Makefile            |    2 
 arch/i386/kernel/cpu/common.c        |    9 
 arch/i386/kernel/cpu/intel.c         |    8 
 arch/i386/kernel/entry.S             |    1 
 arch/i386/kernel/i8259.c             |    6 
 arch/i386/kernel/ldt.c               |   88 +++++++++
 arch/i386/kernel/multiring.c         |  316 +++++++++++++++++++++++++++++++++++
 arch/i386/kernel/process.c           |   52 ++++-
 arch/i386/kernel/ptrace.c            |    8 
 arch/i386/kernel/signal.c            |   24 +-
 arch/i386/kernel/traps.c             |   44 +++-
 arch/i386/mach-generic/irq_vectors.h |   24 +-
 arch/i386/mach-visws/irq_vectors.h   |   22 +-
 arch/i386/math-emu/fpu_entry.c       |    2 
 arch/i386/mm/fault.c                 |    5 
 fs/exec.c                            |    4 
 include/asm-i386/desc.h              |   48 +++++
 include/asm-i386/fixmap.h            |   14 +
 include/asm-i386/idt.h               |  236 ++++++++++++++++++++++++++
 include/asm-i386/ldt.h               |    3 
 include/asm-i386/mmu.h               |   10 +
 include/asm-i386/mmu_context.h       |    8 
 include/asm-i386/multiring.h         |  194 +++++++++++++++++++++
 include/asm-i386/processor.h         |   26 +-
 include/asm-i386/segment.h           |   12 +
 include/asm-i386/system.h            |    6 
 include/asm-i386/unistd.h            |    1 
 include/linux/sched.h                |    8 
 kernel/fork.c                        |    6 
 31 files changed, 1103 insertions(+), 92 deletions(-)










Test program (apologies for the horrible coding style):

/*
  multiring-test.c: example program for Linux multiring support
  
  Copyright (C) 2002 Luca Barbieri <ldb@ldb.ods.org>

  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free
  Software Foundation; either version 2, or (at your option) any later
  version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  for more details.

  You should have received a copy of the GNU General Public License
  along with this program; see the file COPYING.  If not, write to the Free
  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
*/

#include <errno.h>
#include "/home/ldb/src/linux-2.5.44_multiring/include/asm-i386/unistd.h"
#include "/home/ldb/src/linux-2.5.44_multiring/include/asm-i386/multiring.h"
#include "/home/ldb/src/linux-2.5.44_multiring/include/asm-i386/ldt.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#define CLONE_IDT	0x00800000

unsigned ring;
unsigned xcs;

typedef char intbuf_t[4];

intbuf_t test_entry_intbuf;
typedef int (*test_entry_int_t)(unsigned param) __attribute__((regparm(3)));
#define test_entry_int ((test_entry_int_t)test_entry_intbuf)

intbuf_t kernel_syscall_intbuf;

char lower_ring_msg[] = "from lower ring! [should be XXXm...]\n";

void make_int(intbuf_t p, unsigned vec)
{
	p[0] = 0xcd;
	p[1] = vec;
	p[2] = 0xc3;
}

void test_entry();
void test_entry2();
void syscall_entry();

int kernel_syscall(unsigned num, unsigned arg1, unsigned arg2, unsigned arg3)
{
	unsigned ret;
	__asm__ __volatile__ (
	"pushl %%ebx\n\t"
	"movl %2, %%ebx\n\t"
	"call kernel_syscall_intbuf\n\t"
	"popl %%ebx" : "=a" (ret) : "0" (num), "r" (arg1), "c" (arg2), "d" (arg3));
	return ret;
}

int do_test_entry(unsigned param)
{
	printf("test_entry called with: %u\n", param);
	if(param == 99)
	{
		unsigned vec;
		int ret;		
		int testvec;
		vec = multiring_copy_free(0x80);
		printf("copy_free(0x80) ret: %i errno: %i\n", vec, errno);

		printf("alloc_all ");
		for(;;)
		{
			ret = multiring_copy_free(0x80);
			if(ret >= 0)
				printf("%x ", testvec = ret);
			else
			{
				printf("\nret: %i errno: %i [should be -1/28]\n", ret, errno);
				break;
			}
		}
		ret = multiring_free(testvec);
		printf("free testvec: %i ret: %i errno: %i\n", testvec, ret, errno);
		ret = multiring_copy_free(0x80);
		printf("copy_free ret: %i errno: %i\n", ret, errno);
		
		printf("about to multiring_set %x %x\n", (xcs << 16) | ((unsigned long)test_entry2 & 0xffff), ((unsigned long)test_entry2 & 0xffff0000) | 0x8f00 | ((ring + 1) << 13));
		multiring_set(0x80, (xcs << 16) | ((unsigned long)syscall_entry & 0xffff), ((unsigned long)syscall_entry & 0xffff0000) | 0x8f00 | ((ring + 1) << 13));
		make_int(kernel_syscall_intbuf, vec);		
	}
	return param * 2;
}

int do_syscall_entry(unsigned num, unsigned arg1, unsigned arg2, unsigned arg3)
{
	if((num == __NR_write) && (arg1 == 1))
	{
		char* ptr = (char*)arg2;
		ptr[0] = 'X';
		ptr[1] = 'X';
		ptr[2] = 'X';
		return kernel_syscall(num, 1, arg2, arg3);
	}
	else if(num == __NR_exit)
	{
		kernel_syscall(__NR_write, 1, (unsigned long)"quitting\n", strlen("quitting\n"));
		return kernel_syscall(__NR_exit, 0, 0, 0);
	}
	else
	{
		kernel_syscall(__NR_write, 1, (unsigned long)"syscall not allowed\n", strlen("syscall not allowed\n"));
		return -ENOSYS;
	}
}

asm("
test_entry:
pushl %eax
call do_test_entry
addl $4, %esp
iret

test_entry2:
cld
pushl %es
pushl %ds
pushl %eax
movw %ss, %ax
movw %ax, %ds
movw %ax, %es
call do_test_entry
addl $4, %esp
popl %ds
popl %es
iret

syscall_entry:
cld
pushl %es
pushl %ds
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
movw %ss, %ax
movw %ax, %ds
movw %ax, %es

call do_syscall_entry

addl $4, %esp
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popl %ds
popl %es
iret

");

char* entry_stack;
char* lower_stack;
char* clone_stack;

#define ldt_sel(num, ring) (((num) << 3) | (1 << 2) | (ring))

static void interprivilege_jump(unsigned ss, unsigned esp, unsigned cs, unsigned eip) __attribute__((noreturn));

static void interprivilege_jump(unsigned ss, unsigned esp, unsigned cs, unsigned eip)
{
	__asm__ __volatile__(
	"movl %0, %%ds\n\t"
	"movl %0, %%es\n\t"	
	"pushl %0\n\t"
	"pushl %1\n\t"
	"pushfl\n\t"
	"pushl %2\n\t"
	"pushl %3\n\t"
	"iret" : : "r" (ss), "r" (esp), "r" (cs), "r" (eip));
	abort();
}

void lower_ring_start()
{
	test_entry_int(10);
#ifdef CRASH_INT
	/* int 0x80 has DPL 1, so this should crash */
	write(1, lower_ring_msg, strlen(lower_ring_msg));
#endif
	test_entry_int(99);
	write(1, lower_ring_msg, strlen(lower_ring_msg));
#ifdef CRASH_SEGV
	*(unsigned long*)0 = 0;
#endif
	_exit(0);
}

/* this should reboot the processor if we have access to kernel mode memory */
void triple_fault(void)
{
	struct
	{
		unsigned short a;
		struct
		{
			unsigned short lim;
			unsigned long addr;
		} m48;
	} desc;
	/* find the IDT address */
	__asm__ __volatile__("sidt %0" : "=m" (desc.m48));

	/* clear the IDT (or crash, if the kernel works properly) */
	memset((void*)desc.m48.addr, 0, desc.m48.lim + 1);

	/* triple fault */
	*(unsigned long*)0 = 0;
}

#define idt_gate(sel, addr, ring) (((sel) << 16) | ((unsigned long)addr & 0xffff)), (((unsigned long)addr & 0xffff0000) | 0x8f00 | ((ring) << 13))
static inline pid_t syscall_clone(unsigned long flags)
{
	pid_t pid;
	asm volatile("pushl %%ebx\n\tmovl %1, %%ebx\n\tmovl %%esp, %%ecx\n\tint $0x80\n\tpopl %%ebx" : "=a" (pid) : "r" (flags | SIGCHLD), "0" (__NR_clone) : "edx", "memory");
	return pid;
}

unsigned test_vec;

void clone_vm_child(void)
{
	int ret;
	unsigned ccs;
	unsigned css;
	unsigned cring;
	struct multiring_gate gate;	
	ret = multiring_check();
	printf("vm check ret: %i errno: %i\n", ret, errno);
	
	__asm__ __volatile__("movl %%cs, %0" : "=r" (ccs));
	__asm__ __volatile__("movl %%ss, %0" : "=r" (css));
	printf("vm cs: %x ss: %x\n", ccs, css);
	cring = xcs & 3;

	ret = multiring_set(test_vec, idt_gate(ccs, 0x33333333, cring));
	printf("vm set 33333333 ret: %i errno: %i\n", ret, errno);
	ret = multiring_get(test_vec, &gate);
	printf("vm get ret: %i errno: %i a: %x b: %x\n", ret, errno, gate.a, gate.b);
		
	_exit(0);
}

int main(int argc, char** argv)
{
	int ret;
	unsigned xss;
	unsigned test_entry_vec;
	struct multiring_gate gate;
	pid_t pid;
	struct user_desc ldt;
	ret = multiring_elevate();
	printf("elevate ret: %i errno: %i\n", ret, errno);
#ifdef ELEVATE
	return 0;
#endif
	__asm__ __volatile__("movl %%cs, %0" : "=r" (xcs));

	ret = multiring_check();
	printf("check ret: %i errno: %i\n", ret, errno);
	
	printf("cs: %x\n", xcs);
	__asm__ __volatile__("movl %%ss, %0" : "=r" (xss));
	printf("ss: %x\n", xss);
	ring = xcs & 3;
	if(ring == 3)
	{
		printf("we are still at ring 3 :( - exiting\n");
		return 0;
	}

	test_vec = multiring_set_free(idt_gate(xcs, 0x11111111, ring));
	printf("set_free 11111111 ret: %i errno: %i\n", test_vec, errno);
	ret = multiring_get(test_vec, &gate);
	printf("get ret: %i errno: %i a: %x b: %x\n", ret, errno, gate.a, gate.b);
	pid = fork();
	printf("fork pid: %i errno: %i\n", pid, errno);
	if(!pid)
	{
		//for(;;) {}
		ret = multiring_check();
		printf("fork check ret: %i errno: %i\n", ret, errno);

		__asm__ __volatile__("movl %%cs, %0" : "=r" (xcs));
		__asm__ __volatile__("movl %%ss, %0" : "=r" (xss));
		printf("fork cs: %x ss: %x\n", xcs, xss);
		ring = xcs & 3;

		ret = multiring_set(test_vec, idt_gate(xcs, 0x22222222, ring));
		printf("fork set 22222222 ret: %i errno: %i\n", ret, errno);
		ret = multiring_get(test_vec, &gate);
		printf("fork get ret: %i errno: %i a: %x b: %x\n", ret, errno, gate.a, gate.b);
		
		_exit(0);
	}
	else
	{
		int status;
		waitpid(pid, &status, 0);
		printf("status: %x\n", status);
	}
	
	ret = multiring_get(test_vec, &gate);
	printf("get ret: %i errno: %i a: %x b: %x [should be desc for 11111111]\n", ret, errno, gate.a, gate.b);

	pid = clone(clone_vm_child, (char*)malloc(65536) + 65536, CLONE_VM|SIGCHLD, 0);
	printf("CLONE_VM pid: %i errno: %i\n", pid, errno);
	{
		int status;
		waitpid(pid, &status, 0);
		printf("status: %x\n", status);
	}
	
	ret = multiring_get(test_vec, &gate);
	printf("get ret: %i errno: %i a: %x b: %x [should be desc for 33333333]\n", ret, errno, gate.a, gate.b);

	pid = syscall_clone(CLONE_IDT);
	printf("CLONE_IDT pid: %i errno: %i\n", pid, errno);
	if(!pid)
	{
		//for(;;) {}
		ret = multiring_check();
		printf("idt check ret: %i errno: %i\n", ret, errno);
	
		__asm__ __volatile__("movl %%cs, %0" : "=r" (xcs));
		__asm__ __volatile__("movl %%ss, %0" : "=r" (xss));
		printf("idt cs: %x ss: %x\n", xcs, xss);
		ring = xcs & 3;

		ret = multiring_set(test_vec, idt_gate(xcs, 0x44444444, ring));
		printf("idt set 44444444 ret: %i errno: %i\n", ret, errno);
		ret = multiring_get(test_vec, &gate);
		printf("idt get ret: %i errno: %i a: %x b: %x\n", ret, errno, gate.a, gate.b);
		
		_exit(0);
	}
	else
	{
		int status;
		waitpid(pid, &status, 0);
		printf("status: %x\n", status);
	}

	ret = multiring_get(test_vec, &gate);
	printf("get ret: %i errno: %i a: %x b: %x [should be desc for 44444444]\n", ret, errno, gate.a, gate.b);

#ifdef DO_EXEC
	execlp("ls", "ls", 0);
#endif
	
#ifdef EXPLOIT_GDT
	printf("about to exploit with sel = %x\n", xss);
	triple_fault();
#endif

	multiring_set_free(idt_gate(xcs, 0xeeeeeeee, 0));
	printf("multiring_set(gate_to_kernel) ret: %i errno: %i\n", ret, errno);

#ifdef EXPLOIT_IDT
	test_entry_vec = multiring_set_free(idt_gate(xcs, 0xeeeeeeee, 1));
	printf("set_free(to_karea) ret: %i errno: %i\n", test_entry_vec, errno);
#else
	test_entry_vec = multiring_set_free(idt_gate(xcs, test_entry, ring));
	printf("set_free ret: %i errno: %i\n", test_entry_vec, errno);
#endif	

	make_int(test_entry_intbuf, test_entry_vec);
	ret = test_entry_int(42);
	printf("test_entry_int: %u\n", ret);

	/* we could use the initial stack, but it's more difficult */
	entry_stack = malloc(65536);

	ret = multiring_set_espss(ring, (unsigned long)(entry_stack + 65536), xss);
	printf("set_espss ret: %i errno %i esp: %x ss: %x\n", ret, errno, (unsigned long)(entry_stack + 65536), xss);
	{
		unsigned tesp, tss;
		ret = multiring_get_espss(ring, &tesp, &tss);
		printf("get_espss ret: %i errno %i esp: %x ss: %x\n", ret, errno, tesp, tss);
	}
	ret = multiring_set(test_entry_vec, idt_gate(xcs, test_entry2, ring + 1));
	printf("multiring_set(test_entry_vec) ret: %i errno: %i\n", ret, errno);

	/* addresses should not be hardcoded in real programs */
	
	ldt.entry_number = 1;
	ldt.base_addr = 0;
	ldt.limit = 0xaffff;
	ldt.seg_32bit = 1;
	ldt.contents = MODIFY_LDT_CONTENTS_DATA;
	ldt.read_exec_only = 0;
	ldt.limit_in_pages = 1;
	ldt.seg_not_present = 0;
	ldt.useable = 0;
#ifdef EXPLOIT_LDT
	ldt.dpl = ring;
	ldt.limit = 0xfffff;
	ret = modify_ldt(0x11, &ldt, sizeof(struct user_desc));
	printf("modify_ldt(exploit) ret: %i errno: %i\n", test_entry_vec, errno);

	__asm__ __volatile__("movl %0, %%ds\n\tmovl %0, %%es" : : "r" (ldt_sel(1, ring)));
	printf("about to exploit with sel = %x\n", ldt_sel(1, ring));

	triple_fault();
#endif
	ldt.dpl = ring + 1;
	ret = modify_ldt(0x11, &ldt, sizeof(struct user_desc));
	printf("modify_ldt(data) ret: %i errno: %i\n", test_entry_vec, errno);	

	ldt.entry_number = 2;
	ldt.contents = MODIFY_LDT_CONTENTS_CODE;
	modify_ldt(0x11, &ldt, sizeof(struct user_desc));
	printf("modify_ldt(code) ret: %i errno: %i\n", test_entry_vec, errno);		

	lower_stack = malloc(65536);

	interprivilege_jump(ldt_sel(1, ring + 1), (unsigned long)(lower_stack + 65536), ldt_sel(2, ring + 1), (unsigned long)lower_ring_start);
	return 0;
}










Patch:

diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/Config.help linux-2.5.44_multiring/arch/i386/Config.help
--- linux-2.5.44/arch/i386/Config.help	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/Config.help	2002-10-27 00:44:02.000000000 +0200
@@ -165,6 +165,13 @@ CONFIG_HIGHPTE
   low memory.  Setting this option will put user-space page table
   entries in high memory.
 
+CONFIG_HIGHIDT
+  The kernel uses 4KB for each multiring process (e.g. User Mode Linux).
+  Say Y to allocate those 4KB in high memory. This is only useful if you
+  plan to run hundreds of thousands of multiring processes.
+
+  If unsure, say N.
+
 CONFIG_HIGHMEM4G
   Select this if you have a 32-bit processor and between 1 and 4
   gigabytes of physical RAM.
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/config.in linux-2.5.44_multiring/arch/i386/config.in
--- linux-2.5.44/arch/i386/config.in	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/config.in	2002-10-27 00:44:02.000000000 +0200
@@ -236,6 +236,7 @@ fi
 
 if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then
    bool 'Allocate 3rd-level pagetables from highmem' CONFIG_HIGHPTE
+   bool 'Allocate multiring IDTs from highmem (EXPERIMENTAL)' CONFIG_X86_HIGHIDT
 fi
 
 bool 'Math emulation' CONFIG_MATH_EMULATION
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/cpu/common.c linux-2.5.44_multiring/arch/i386/kernel/cpu/common.c
--- linux-2.5.44/arch/i386/kernel/cpu/common.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/cpu/common.c	2002-10-27 00:44:02.000000000 +0200
@@ -243,6 +243,8 @@ void __init generic_identify(struct cpui
 	}
 }
 
+extern void load_idt_table_init(unsigned cpu, pgprot_t prot);
+
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
@@ -257,6 +259,7 @@ void __init identify_cpu(struct cpuinfo_
 	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
 	c->x86_vendor_id[0] = '\0'; /* Unset */
 	c->x86_model_id[0] = '\0';  /* Unset */
+	c->f00f_bug = 0;
 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
 	if (!have_cpuid_p()) {
@@ -348,6 +351,9 @@ void __init identify_cpu(struct cpuinfo_
 		/* AND the already accumulated flags with these */
 		for ( i = 0 ; i < NCAPINTS ; i++ )
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+
+		if(c->f00f_bug)
+			boot_cpu_data.f00f_bug = 1;
 	}
 
 	printk(KERN_DEBUG "CPU:             Common caps: %08lx %08lx %08lx %08lx\n",
@@ -355,6 +361,9 @@ void __init identify_cpu(struct cpuinfo_
 	       boot_cpu_data.x86_capability[1],
 	       boot_cpu_data.x86_capability[2],
 	       boot_cpu_data.x86_capability[3]);
+
+	/* load the IDT */
+	load_idt_table_init((c == &boot_cpu_data) ? 0 : (c - cpu_data), boot_cpu_data.f00f_bug ? PAGE_KERNEL_RO : PAGE_KERNEL);	
 }
 /*
  *	Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/cpu/intel.c linux-2.5.44_multiring/arch/i386/kernel/cpu/intel.c
--- linux-2.5.44/arch/i386/kernel/cpu/intel.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/cpu/intel.c	2002-10-27 00:44:02.000000000 +0200
@@ -169,15 +169,13 @@ static void __init init_intel(struct cpu
 	 * have the F0 0F bug, which lets nonpriviledged users lock up the system.
 	 * Note that the workaround only should be initialized once...
 	 */
-	c->f00f_bug = 0;
 	if ( c->x86 == 5 ) {
-		static int f00f_workaround_enabled = 0;
+		static int f00f_workaround_message = 0;
 
 		c->f00f_bug = 1;
-		if ( !f00f_workaround_enabled ) {
-			trap_init_f00f_bug();
+		if ( !f00f_workaround_message ) {
 			printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
-			f00f_workaround_enabled = 1;
+			f00f_workaround_message = 1;
 		}
 	}
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/entry.S linux-2.5.44_multiring/arch/i386/kernel/entry.S
--- linux-2.5.44/arch/i386/kernel/entry.S	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/entry.S	2002-10-27 00:44:02.000000000 +0200
@@ -737,6 +737,7 @@ ENTRY(sys_call_table)
 	.long sys_free_hugepages
 	.long sys_exit_group
 	.long sys_lookup_dcookie
+	.long sys_multiring
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/i8259.c linux-2.5.44_multiring/arch/i386/kernel/i8259.c
--- linux-2.5.44/arch/i386/kernel/i8259.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/i8259.c	2002-10-27 00:44:02.000000000 +0200
@@ -282,7 +282,8 @@ void init_8259A(int auto_eoi)
 	 * outb_p - this has to work on a wide range of PC hardware.
 	 */
 	outb_p(0x11, 0x20);	/* ICW1: select 8259A-1 init */
-	outb_p(0x20 + 0, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+	/* ICW2: 8259A-1 IR0-7 mapped to FIRST_EXTERNAL_VECTOR-FIRST_EXTERNAL_VECTOR+7 */
+	outb_p(FIRST_EXTERNAL_VECTOR + 0, 0x21);
 	outb_p(0x04, 0x21);	/* 8259A-1 (the master) has a slave on IR2 */
 	if (auto_eoi)
 		outb_p(0x03, 0x21);	/* master does Auto EOI */
@@ -290,7 +291,8 @@ void init_8259A(int auto_eoi)
 		outb_p(0x01, 0x21);	/* master expects normal EOI */
 
 	outb_p(0x11, 0xA0);	/* ICW1: select 8259A-2 init */
-	outb_p(0x20 + 8, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+	/* ICW2: 8259A-2 IR0-7 mapped to FIRST_EXTERNAL_VECTOR+8-FIRST_EXTERNAL_VECTOR+f */
+	outb_p(FIRST_EXTERNAL_VECTOR + 8, 0xA1);
 	outb_p(0x02, 0xA1);	/* 8259A-2 is a slave on master's IR2 */
 	outb_p(0x01, 0xA1);	/* (slave's support for AEOI in flat mode
 				    is to be investigated) */
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/ldt.c linux-2.5.44_multiring/arch/i386/kernel/ldt.c
--- linux-2.5.44/arch/i386/kernel/ldt.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/ldt.c	2002-10-27 02:18:48.000000000 +0200
@@ -18,6 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
+#include <asm/idt.h>
 
 #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
 static void flush_ldt(void *null)
@@ -81,22 +82,62 @@ static inline int copy_ldt(mm_context_t 
 	return 0;
 }
 
+static inline int copy_idt(mm_context_t* new, mm_context_t* old, unsigned flags)
+{
+	struct desc_struct* oldidt;
+	if(flags & (CLONE_VM | CLONE_IDT))
+	{
+		oldidt = kmap_idt(old);
+		atomic_inc(idt_refcnt(oldidt));
+		kunmap_idt(old, oldidt);
+		new->idt = old->idt;
+	}
+	else
+	{
+		struct desc_struct* newidt;
+		union idt idtu;
+		
+		newidt = alloc_idt(&idtu);
+		if(!newidt)
+			return -ENOMEM;
+		oldidt = kmap_read_idt(old);
+		memcpy(newidt, oldidt, IDT_SIZE);
+		kunmap_read_idt(old, oldidt);
+		kunmap_new_idt(&idtu, newidt);
+		wmb();
+		new->idt = idtu;
+	}
+	return 0;
+}
+
 /*
  * we do not have to muck with descriptors here, that is
  * done in switch_mm() as needed.
  */
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+int init_new_context_flags(struct task_struct *tsk, struct mm_struct *mm, unsigned flags)
 {
 	struct mm_struct * old_mm;
 	int retval = 0;
 
 	init_MUTEX(&mm->context.sem);
 	mm->context.size = 0;
+	mm->context.idt.opaque = 0;
+	mm->context.bad_segments = 0;	
 	old_mm = current->mm;
-	if (old_mm && old_mm->context.size > 0) {
-		down(&old_mm->context.sem);
-		retval = copy_ldt(&mm->context, &old_mm->context);
-		up(&old_mm->context.sem);
+	if (old_mm)
+	{
+		mm->context.bad_segments = old_mm->context.bad_segments;
+		if(old_mm->context.size > 0 || (old_mm->context.idt.opaque && !(flags & CLONE_CLEAR_IDT)))
+		{
+			down(&old_mm->context.sem);
+			mm->context.bad_segments = old_mm->context.bad_segments;			
+			retval = 0;
+			if(old_mm->context.size > 0)
+				retval = copy_ldt(&mm->context, &old_mm->context);
+			if(!retval && old_mm->context.idt.opaque && !(flags & CLONE_CLEAR_IDT))
+				retval = copy_idt(&mm->context, &old_mm->context, flags);
+			up(&old_mm->context.sem);
+		}
 	}
 	return retval;
 }
@@ -115,6 +156,8 @@ void release_segments(struct mm_struct *
 			kfree(mm->context.ldt);
 		mm->context.size = 0;
 	}
+	if(mm->context.idt.opaque)
+		free_idt(&mm->context);
 }
 
 static int read_ldt(void * ptr, unsigned long bytecount)
@@ -189,6 +232,10 @@ static int write_ldt(void * ptr, unsigne
 			goto out;
 	}
 
+	error = LDT_handle_perm(&ldt_info, &mm->context);
+	if(error)
+		goto out;
+
 	down(&mm->context.sem);
 	if (ldt_info.entry_number >= mm->context.size) {
 		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
@@ -211,10 +258,22 @@ static int write_ldt(void * ptr, unsigne
 	entry_2 = LDT_entry_b(&ldt_info);
 	if (oldmode)
 		entry_2 &= ~(1 << 20);
+	if(mm->context.idt.opaque)
+	{
+		error = -EINVAL;
+		if(ldt_info.dpl == 0)
+			goto out_unlock;
+		entry_2 = (entry_2 & ~(3 << 13)) | (ldt_info.dpl << 13);		
+	}
 
 	/* Install the new entry ...  */
 install:
+	*(lp+1) = 0;
+	wmb();
+	
 	*lp	= entry_1;
+	wmb();
+
 	*(lp+1)	= entry_2;
 	error = 0;
 
@@ -244,3 +303,22 @@ asmlinkage int sys_modify_ldt(int func, 
 	}
 	return ret;
 }
+
+int LDT_handle_over_page_offset(mm_context_t* ctx)
+{
+	if(ctx->idt.opaque)
+		return -EPERM;
+	else if(ctx->bad_segments)
+		return 0;
+	else
+	{
+		int ret = 0;
+		down(&ctx->sem);
+		if(ctx->idt.opaque)
+			ret = -EPERM;
+		else
+			ctx->bad_segments = 1;
+		up(&ctx->sem);
+		return ret;
+	}
+}
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/Makefile linux-2.5.44_multiring/arch/i386/kernel/Makefile
--- linux-2.5.44/arch/i386/kernel/Makefile	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/Makefile	2002-10-27 00:44:03.000000000 +0200
@@ -9,7 +9,7 @@ export-objs     := mca.o i386_ksyms.o ti
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
-		bootflag.o
+		bootflag.o multiring.o
 
 obj-y				+= cpu/
 obj-y				+= timers/
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/multiring.c linux-2.5.44_multiring/arch/i386/kernel/multiring.c
--- linux-2.5.44/arch/i386/kernel/multiring.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/multiring.c	2002-10-27 03:18:02.000000000 +0100
@@ -0,0 +1,316 @@
+/*
+ * linux/kernel/multiring.c: support for multiple privilege rings
+ *
+ * Copyright (C) 2002 Luca Barbieri <ldb@ldb.ods.org>
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/idt.h>
+#include <asm/irq.h>
+#include <asm/multiring.h>
+
+#define MULTIRING_NR_VECTORS ((MULTIRING_AUTO_LAST_VECTOR - MULTIRING_AUTO_FIRST_VECTOR + 1) + (MULTIRING_SPECIAL_LAST_VECTOR - MULTIRING_SPECIAL_FIRST_VECTOR + 1) + 1)
+
+static unsigned char vec2idx[256];
+static unsigned char idx2vec[MULTIRING_NR_VECTORS];
+
+#ifdef CONFIG_SMP /* avoids "defined but not used" warning */
+static void flush_idt(void *null)
+{
+	if (current->active_mm)
+		load_IDT(&current->active_mm->context);
+}
+#endif
+
+static inline unsigned multiring_fix_selector(unsigned sel)
+{
+	unsigned tsel = sel | 3;
+	if(tsel == USER_DS_RPL(3))
+		return USER_DS_RPL(MULTIRING_USER_RING);
+	else if(tsel == USER_CS_RPL(3))
+		return USER_CS_RPL(MULTIRING_USER_RING);
+	else
+		return sel;
+}
+
+static inline void multiring_fix_selector_ptr(unsigned* sel)
+{
+	*sel = multiring_fix_selector(*sel);
+}
+
+static inline struct pt_regs* get_pt_regs(task_t* tsk)
+{
+	return (struct pt_regs*)tsk->thread.esp0 - 1;
+}
+
+void multiring_init_task(task_t* tsk)
+{		
+		/* One-time initialization for multiring mode */
+		unsigned oldsel, newsel;
+		struct pt_regs* regs;
+		
+		regs = get_pt_regs(tsk);
+
+#define multiring_fix_loaded_selector(selname) \
+		savesegment(selname, oldsel); \
+		newsel = multiring_fix_selector(oldsel); \
+		if(oldsel != newsel) \
+			loadsegment(selname, oldsel);
+		
+		multiring_fix_selector_ptr((unsigned*)&regs->xds);
+		multiring_fix_selector_ptr((unsigned*)&regs->xes);
+		multiring_fix_selector_ptr((unsigned*)&regs->xcs);
+		multiring_fix_selector_ptr((unsigned*)&regs->xss);
+		if(tsk != current)
+		{
+			multiring_fix_selector_ptr((unsigned*)&tsk->thread.fs);
+			multiring_fix_selector_ptr((unsigned*)&tsk->thread.gs);
+		}
+		else
+		{
+			multiring_fix_loaded_selector(fs);
+			multiring_fix_loaded_selector(gs);
+		}
+#undef multiring_fix_loaded_selector
+}
+
+void load_IDT_nolock(mm_context_t* ctx, unsigned cpu)
+{
+	load_IDT_nolock_inline(current, ctx, cpu);
+}
+
+asmlinkage int sys_multiring(unsigned op, unsigned arg1, unsigned arg2, unsigned arg3)
+{
+	mm_context_t* ctx = &current->mm->context;
+	int ret;
+	unsigned i;
+	int cpu;
+	struct desc_struct gate;
+	struct desc_struct* idt;
+
+	/* Without WP, DPL 1 and 2 will bypass copy-on-write */
+	if(!boot_cpu_data.wp_works_ok)
+		return -ENOSYS;
+		
+	if(op > MULTIRING_LAST_OP)
+		return -EOPNOTSUPP;
+
+	switch(op)
+	{
+	case MULTIRING_CHECK:
+		return current->thread.multiring_mode ? 0 : (ctx->bad_segments ? -EPERM : 1);
+
+	case MULTIRING_SET_ESPSS:
+	{
+		struct tss_struct *tss;
+		unsigned ring = arg1;
+		unsigned esp = arg2;
+		unsigned ss = arg3;
+		if(ring == 0)
+			return -EPERM;
+		if(ring >= 3 || ring != (ss & 3))
+			return -EINVAL;
+
+		current->thread.espss12[ring - 1].esp = esp;
+		current->thread.espss12[ring - 1].ss  = ss;
+
+		cpu = get_cpu();
+		tss = init_tss + cpu;
+		tss->espss12[ring - 1].esp = esp;
+		tss->espss12[ring - 1].ss  = ss;
+		put_cpu();
+
+		return 0;
+	}
+	
+	case MULTIRING_GET_ESPSS:
+	{
+		unsigned ring = arg1;
+		unsigned* esp = (unsigned*)arg2;
+		unsigned* ss = (unsigned*)arg3;		
+		if(ring == 0)
+			return -EPERM;
+		if(ring >= 3)
+			return -EINVAL;
+		
+		if(put_user(current->thread.espss12[ring - 1].esp, esp)
+		   || put_user(current->thread.espss12[ring - 1].ss, ss))
+			return -EFAULT;
+		return 0;
+	}
+
+	case MULTIRING_GET_RANGE:
+	{
+		unsigned first, last;
+		char* ptr = (char*)arg3;
+		if(arg1 <= arg2)
+		{
+			first = arg1;
+			last = arg2;
+		}
+		else
+		{
+			first = arg2;
+			last = arg1;
+		}
+
+		ret = (last - first + 1) * 8;
+		idt = kmap_read_idt_or_table(ctx);
+		if(copy_to_user(ptr, &idt[first], ret))
+			ret = -EFAULT;
+		kunmap_read_idt_or_table(ctx, idt);
+		return ret;
+	}
+
+	case MULTIRING_GET:
+	{
+		unsigned vec = arg1;
+		unsigned* ptr = (unsigned*)arg2;
+		ret = 0;
+		idt = kmap_read_idt_or_table(ctx);
+		if(copy_to_user(ptr, &idt[vec], 8))
+			ret = -EFAULT;
+		kunmap_read_idt_or_table(ctx, idt);
+		return ret;	
+	}
+	}
+	
+	if(!current->thread.multiring_mode)
+	{
+		if(op != MULTIRING_ELEVATE)
+			return -ENXIO;
+		
+		if(ctx->bad_segments)
+			return -EPERM;
+
+		down(&ctx->sem);
+		ret = -EPERM;
+		if(ctx->bad_segments)
+			goto out_up;
+
+		if(!ctx->idt.opaque)
+		{
+			union idt idtu;
+			idt = alloc_idt(&idtu);
+			ret = -ENOMEM;
+			if(!idt)
+				goto out_up;
+			memcpy(idt, idt_table, IDT_SIZE);
+			idt[SYSCALL_VECTOR].b = (idt[SYSCALL_VECTOR].b &~ 0x6000) | (MULTIRING_USER_RING << 13);
+			kunmap_new_idt(&idtu, idt);
+
+			wmb();
+			ctx->idt = idtu;
+			wmb();
+
+#ifdef CONFIG_SMP
+			cpu = get_cpu();
+			if (current->mm->cpu_vm_mask != (1 << cpu))
+				smp_call_function(flush_idt, 0, 1, 1);
+			put_cpu();
+#endif
+		}
+		up(&ctx->sem);
+
+		cpu = get_cpu();
+		if(!current->thread.multiring_mode)
+			load_IDT_nolock(ctx, cpu);
+		put_cpu();
+		return 0;
+
+	  out_up:
+		up(&ctx->sem);
+		return ret;
+	}
+	
+	/* MULTIRING_SET or MULTIRING_COPY */
+	{
+		unsigned vec = arg1;
+		idt = kmap_write_idt(ctx);
+		if(vec == MULTIRING_VEC_FREE)
+		{
+			for(i = 0; i < MULTIRING_NR_VECTORS; ++i)
+			{
+				vec = idx2vec[i];
+				if(!idt[vec].a && !idt[vec].b)
+					goto found_free;
+			}
+			ret = -ENOSPC;
+			goto out_put_idt;
+		  found_free:
+		}
+		else
+		{
+			ret = -EPERM;
+			if(vec2idx[vec] == (unsigned char)~0)
+				goto out_put_idt;
+		}
+
+		if(op == MULTIRING_COPY)
+		{
+			unsigned from = arg2;
+			ret = -EPERM;
+			if(vec2idx[from] == (unsigned char)~0)
+				goto out_put_idt;
+			gate = idt[from];
+		}
+		else
+		{
+			gate.a = arg2;
+			gate.b = arg3;
+			if(gate.b & 0x8000)
+			{
+				ret = -EINVAL;
+				if((gate.b & 0x10ff) || (~gate.b & 0x700) || !(gate.b & 0x6000)) /* reserved_is_bad || !trap_gate || dpl0 */
+					goto out_put_idt;
+				ret = -EPERM;
+				if(!(gate.a & 0x30000) && (gate.a >> 16) && (gate.a != idt_table[SYSCALL_VECTOR].a || (gate.b | 0xe000) != idt_table[SYSCALL_VECTOR].b)) /* seg_RPL == 0 && not_int80_syscall */
+					goto out_put_idt;
+			}
+		}
+
+		idt[vec].b = 0;
+		wmb();
+		idt[vec].a = gate.a;
+		wmb();
+		idt[vec].b = gate.b;
+		ret = vec;
+	}
+  out_put_idt:
+	kunmap_write_idt(ctx, idt);
+	return ret;
+}
+
+int __init init_multiring(void)
+{
+	unsigned idx;
+	unsigned vec;
+
+	memset(vec2idx, 0xff, sizeof(vec2idx));
+	idx = 0;
+	for(vec = MULTIRING_AUTO_FIRST_VECTOR; vec <= MULTIRING_AUTO_LAST_VECTOR; ++vec, ++idx)
+		idx2vec[idx] = vec;
+	for(vec = MULTIRING_SPECIAL_FIRST_VECTOR; vec <= MULTIRING_SPECIAL_LAST_VECTOR; ++vec, ++idx)
+		idx2vec[idx] = vec;
+	idx2vec[idx] = SYSCALL_VECTOR;
+	vec2idx[SYSCALL_VECTOR] = idx;
+
+	for(idx = 0; idx < (MULTIRING_NR_VECTORS - 1); ++idx)
+	{
+		vec = idx2vec[idx];
+		vec2idx[vec] = idx;
+		idt_table[vec].a = 0;
+		idt_table[vec].b = 0;
+	}
+	return 0;
+}
+
+__initcall(init_multiring);
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/process.c linux-2.5.44_multiring/arch/i386/kernel/process.c
--- linux-2.5.44/arch/i386/kernel/process.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/process.c	2002-10-27 02:34:41.000000000 +0200
@@ -40,6 +40,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/ldt.h>
+#include <asm/idt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/desc.h>
@@ -252,6 +253,8 @@ void flush_thread(void)
 	 */
 	clear_fpu(tsk);
 	tsk->used_math = 0;
+	tsk->thread.multiring_mode = 0;
+	load_IDT(&tsk->mm->context);
 }
 
 void release_thread(struct task_struct *dead_task)
@@ -268,18 +271,13 @@ void release_thread(struct task_struct *
 	}
 }
 
-/*
- * Save a segment.
- */
-#define savesegment(seg,value) \
-	asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
-
 int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 	unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
 	struct task_struct *tsk;
+	tsk = current;
 
 	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
 	struct_cpy(childregs, regs);
@@ -289,13 +287,14 @@ int copy_thread(int nr, unsigned long cl
 
 	p->thread.esp = (unsigned long) childregs;
 	p->thread.esp0 = (unsigned long) (childregs+1);
+	p->thread.espss12[0] = tsk->thread.espss12[0];
+	p->thread.espss12[1] = tsk->thread.espss12[1];
 
 	p->thread.eip = (unsigned long) ret_from_fork;
 
 	savesegment(fs,p->thread.fs);
 	savesegment(gs,p->thread.gs);
 
-	tsk = current;
 	unlazy_fpu(tsk);
 	struct_cpy(&p->thread.i387, &tsk->thread.i387);
 
@@ -307,6 +306,8 @@ int copy_thread(int nr, unsigned long cl
 			IO_BITMAP_BYTES);
 	}
 
+	p->thread.multiring_mode = (tsk->thread.multiring_mode && p->mm->context.idt.opaque) ? 1 : 0;
+	
 	/*
 	 * Set a new TLS for the child thread?
 	 */
@@ -319,6 +320,8 @@ int copy_thread(int nr, unsigned long cl
 			return -EFAULT;
 		if (LDT_empty(&info))
 			return -EINVAL;
+		if (LDT_handle_perm(&info, &p->mm->context))
+			return -EPERM;
 
 		idx = info.entry_number;
 		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
@@ -327,6 +330,12 @@ int copy_thread(int nr, unsigned long cl
 		desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
 		desc->a = LDT_entry_a(&info);
 		desc->b = LDT_entry_b(&info);
+		if(unlikely(current->mm->context.idt.opaque))
+		{
+			if(unlikely(info.dpl == 0))
+				return -EINVAL;
+			desc->b = (desc->b & ~(3 << 13)) | (info.dpl << 13);
+		}
 	}
 	return 0;
 }
@@ -420,6 +429,10 @@ void __switch_to(struct task_struct *pre
 	 */
 	tss->esp0 = next->esp0;
 
+	/* multiring */
+	tss->espss12[0] = next->espss12[0];
+	tss->espss12[1] = next->espss12[1];	
+	
 	/*
 	 * Load the per-thread Thread-Local Storage descriptor.
 	 */
@@ -599,8 +612,12 @@ asmlinkage int sys_set_thread_area(struc
 
 	if (copy_from_user(&info, u_info, sizeof(info)))
 		return -EFAULT;
-	idx = info.entry_number;
 
+	if (LDT_handle_perm(&info, &current->mm->context))
+		return -EPERM;
+	
+	idx = info.entry_number;
+	
 	/*
 	 * index -1 means the kernel should try to find and
 	 * allocate an empty descriptor:
@@ -618,20 +635,25 @@ asmlinkage int sys_set_thread_area(struc
 
 	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
 
-	/*
-	 * We must not get preempted while modifying the TLS.
-	 */
-	cpu = get_cpu();
-
 	if (LDT_empty(&info)) {
 		desc->a = 0;
 		desc->b = 0;
 	} else {
 		desc->a = LDT_entry_a(&info);
 		desc->b = LDT_entry_b(&info);
+		if(unlikely(current->mm->context.idt.opaque))
+		{
+			if(unlikely(info.dpl == 0))
+				return -EINVAL;
+			desc->b = (desc->b & ~(3 << 13)) | (info.dpl << 13);
+		}
 	}
-	load_TLS(t, cpu);
 
+	/*
+	 * We must not get preempted while modifying the TLS.
+	 */	
+	cpu = get_cpu();	
+	load_TLS(t, cpu);
 	put_cpu();
 
 	return 0;
@@ -656,6 +678,7 @@ asmlinkage int sys_set_thread_area(struc
 #define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
 #define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
 #define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+#define GET_DPL(desc)		(((desc)->b >> 13) & 3)
 
 asmlinkage int sys_get_thread_area(struct user_desc *u_info)
 {
@@ -679,6 +702,7 @@ asmlinkage int sys_get_thread_area(struc
 	info.limit_in_pages = GET_LIMIT_PAGES(desc);
 	info.seg_not_present = !GET_PRESENT(desc);
 	info.useable = GET_USEABLE(desc);
+	info.dpl = GET_DPL(desc);
 
 	if (copy_to_user(u_info, &info, sizeof(info)))
 		return -EFAULT;
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/ptrace.c linux-2.5.44_multiring/arch/i386/kernel/ptrace.c
--- linux-2.5.44/arch/i386/kernel/ptrace.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/ptrace.c	2002-10-27 00:44:03.000000000 +0200
@@ -76,24 +76,24 @@ static int putreg(struct task_struct *ch
 {
 	switch (regno >> 2) {
 		case FS:
-			if (value && (value & 3) != 3)
+			if (value && !(value & 3))
 				return -EIO;
 			child->thread.fs = value;
 			return 0;
 		case GS:
-			if (value && (value & 3) != 3)
+			if (value && !(value & 3))
 				return -EIO;
 			child->thread.gs = value;
 			return 0;
 		case DS:
 		case ES:
-			if (value && (value & 3) != 3)
+			if (value && !(value & 3))
 				return -EIO;
 			value &= 0xffff;
 			break;
 		case SS:
 		case CS:
-			if ((value & 3) != 3)
+			if (!(value & 3))
 				return -EIO;
 			value &= 0xffff;
 			break;
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/signal.c linux-2.5.44_multiring/arch/i386/kernel/signal.c
--- linux-2.5.44/arch/i386/kernel/signal.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/signal.c	2002-10-27 00:44:03.000000000 +0200
@@ -162,7 +162,7 @@ restore_sigcontext(struct pt_regs *regs,
 #define COPY_SEG_STRICT(seg)						\
 	{ unsigned short tmp;						\
 	  err |= __get_user(tmp, &sc->seg);				\
-	  regs->x##seg = tmp|3; }
+	  regs->x##seg = (tmp & 3) ? tmp : (tmp | USER_RING); }
 
 #define GET_SEG(seg)							\
 	{ unsigned short tmp;						\
@@ -338,7 +338,7 @@ get_sigframe(struct k_sigaction *ka, str
 	}
 
 	/* This is the legacy signal stack switching. */
-	else if ((regs->xss & 0xffff) != __USER_DS &&
+	else if ((regs->xss & 0xfffc) != USER_DS_RPL(0) &&
 		 !(ka->sa.sa_flags & SA_RESTORER) &&
 		 ka->sa.sa_restorer) {
 		esp = (unsigned long) ka->sa.sa_restorer;
@@ -350,6 +350,7 @@ get_sigframe(struct k_sigaction *ka, str
 static void setup_frame(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs * regs)
 {
+	unsigned ring;
 	struct sigframe *frame;
 	int err = 0;
 
@@ -398,10 +399,10 @@ static void setup_frame(int sig, struct 
 	regs->eip = (unsigned long) ka->sa.sa_handler;
 
 	set_fs(USER_DS);
-	regs->xds = __USER_DS;
-	regs->xes = __USER_DS;
-	regs->xss = __USER_DS;
-	regs->xcs = __USER_CS;
+	ring = get_user_ring();
+	regs->xds = regs->xes = regs->xss = USER_DS_RPL(ring);
+	regs->xcs = USER_CS_RPL(ring);
+	put_user_ring();
 	regs->eflags &= ~TF_MASK;
 
 #if DEBUG_SIG
@@ -422,6 +423,7 @@ static void setup_rt_frame(int sig, stru
 {
 	struct rt_sigframe *frame;
 	int err = 0;
+	unsigned ring;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
@@ -473,10 +475,10 @@ static void setup_rt_frame(int sig, stru
 	regs->eip = (unsigned long) ka->sa.sa_handler;
 
 	set_fs(USER_DS);
-	regs->xds = __USER_DS;
-	regs->xes = __USER_DS;
-	regs->xss = __USER_DS;
-	regs->xcs = __USER_CS;
+	ring = get_user_ring();
+	regs->xds = regs->xes = regs->xss = USER_DS_RPL(ring);
+	regs->xcs = USER_CS_RPL(ring);
+	put_user_ring();
 	regs->eflags &= ~TF_MASK;
 
 #if DEBUG_SIG
@@ -556,7 +558,7 @@ int do_signal(struct pt_regs *regs, sigs
 	 * kernel mode. Just return without doing anything
 	 * if so.
 	 */
-	if ((regs->xcs & 3) != 3)
+	if (!(regs->xcs & 3))
 		return 1;
 
 	if (current->flags & PF_FREEZE) {
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/kernel/traps.c linux-2.5.44_multiring/arch/i386/kernel/traps.c
--- linux-2.5.44/arch/i386/kernel/traps.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/kernel/traps.c	2002-10-27 00:44:03.000000000 +0200
@@ -49,6 +49,8 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 
+#include <asm/idt.h>
+
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
 asmlinkage void lcall27(void);
@@ -62,6 +64,10 @@ struct desc_struct default_ldt[] = { { 0
  * for this.
  */
 struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_F00F_BUG)
+pte_t* idt_pte;
+pte_t idt_table_pte;
+#endif
 
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
@@ -249,6 +255,30 @@ bad:
 	printk("\n");
 }	
 
+void __init load_idt_table_init(unsigned cpu, pgprot_t prot)
+{
+	struct Xgt_desc_struct map_idt_descr;
+	
+	if(use_highidt
+#ifdef CONFIG_X86_F00F_BUG
+	   || (pgprot_val(prot) == __PAGE_KERNEL_RO)
+#endif	   
+	)
+	{
+		unsigned idt_vstart;
+		idt_vstart = __fix_to_virt(FIX_IDT_BEGIN);
+		idt_pte = pte_offset_kernel(pmd_offset(pgd_offset_k(idt_vstart), (idt_vstart)), (idt_vstart));
+		
+		idt_table_pte = pfn_pte(__pa(idt_table) >> PAGE_SHIFT, prot);
+		set_pte(idt_pte - cpu, idt_table_pte);
+		map_idt_descr.size = IDT_SIZE - 1;
+		map_idt_descr.address = __fix_to_virt(FIX_IDT_BEGIN + cpu);
+		__asm__ __volatile__("lidt %0": "=m" (map_idt_descr));
+	}
+	else
+		__asm__ __volatile__("lidt %0": "=m" (idt_descr));
+}
+
 static void handle_BUG(struct pt_regs *regs)
 {
 	unsigned short ud2;
@@ -814,20 +844,6 @@ asmlinkage void math_emulate(long arg)
 
 #endif /* CONFIG_MATH_EMULATION */
 
-#ifdef CONFIG_X86_F00F_BUG
-void __init trap_init_f00f_bug(void)
-{
-	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
-
-	/*
-	 * Update the IDT descriptor and reload the IDT so that
-	 * it uses the read-only mapped virtual address.
-	 */
-	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
-	__asm__ __volatile__("lidt %0": "=m" (idt_descr));
-}
-#endif
-
 #define _set_gate(gate_addr,type,dpl,addr) \
 do { \
   int __d0, __d1; \
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/mach-generic/irq_vectors.h linux-2.5.44_multiring/arch/i386/mach-generic/irq_vectors.h
--- linux-2.5.44/arch/i386/mach-generic/irq_vectors.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/mach-generic/irq_vectors.h	2002-10-27 00:44:03.000000000 +0200
@@ -22,16 +22,19 @@
 #ifndef _ASM_IRQ_VECTORS_H
 #define _ASM_IRQ_VECTORS_H
 
+#define MULTIRING_SPECIAL_FIRST_VECTOR	0x20
+#define MULTIRING_SPECIAL_LAST_VECTOR	0x2f
+
 /*
  * IDT vectors usable for external interrupt sources start
- * at 0x20:
+ * at 0x30:
  */
-#define FIRST_EXTERNAL_VECTOR	0x20
+#define FIRST_EXTERNAL_VECTOR	0x30
 
 #define SYSCALL_VECTOR		0x80
 
 /*
- * Vectors 0x20-0x2f are used for ISA interrupts.
+ * Vectors 0x30-0x3f are used for ISA interrupts.
  */
 
 /*
@@ -49,6 +52,9 @@
 #define RESCHEDULE_VECTOR	0xfc
 #define CALL_FUNCTION_VECTOR	0xfb
 
+#define MULTIRING_AUTO_LAST_VECTOR	0xfa
+#define MULTIRING_AUTO_FIRST_VECTOR	0xf1
+
 #define THERMAL_APIC_VECTOR	0xf0
 /*
  * Local APIC timer IRQ vector is on a different priority level,
@@ -58,26 +64,26 @@
 #define LOCAL_TIMER_VECTOR	0xef
 
 /*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
+ * First APIC vector available to drivers: (vectors 0x41-0xee)
+ * we start at 0x41 to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_DEVICE_VECTOR	0x41
 #define FIRST_SYSTEM_VECTOR	0xef
 
 #define TIMER_IRQ 0
 
 /*
- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+ * 16 8259A IRQ's, 192 potential APIC interrupt sources.
  * Right now the APIC is mostly only used for SMP.
  * 256 vectors is an architectural limit. (we can have
  * more than 256 devices theoretically, but they will
  * have to use shared interrupts)
  * Since vectors 0x00-0x1f are used/reserved for the CPU,
- * the usable vector space is 0x20-0xff (224 vectors)
+ * the usable vector space is 0x30-0xff (208 vectors)
  */
 #ifdef CONFIG_X86_IO_APIC
-#define NR_IRQS 224
+#define NR_IRQS 208
 #else
 #define NR_IRQS 16
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/mach-visws/irq_vectors.h linux-2.5.44_multiring/arch/i386/mach-visws/irq_vectors.h
--- linux-2.5.44/arch/i386/mach-visws/irq_vectors.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/mach-visws/irq_vectors.h	2002-10-27 00:44:03.000000000 +0200
@@ -1,11 +1,14 @@
 #ifndef _ASM_IRQ_VECTORS_H
 #define _ASM_IRQ_VECTORS_H
 
+#define MULTIRING_SPECIAL_FIRST_VECTOR	0x20
+#define MULTIRING_SPECIAL_LAST_VECTOR	0x2f
+
 /*
  * IDT vectors usable for external interrupt sources start
- * at 0x20:
+ * at 0x30:
  */
-#define FIRST_EXTERNAL_VECTOR	0x20
+#define FIRST_EXTERNAL_VECTOR	0x30
 
 #define SYSCALL_VECTOR		0x80
 
@@ -28,6 +31,9 @@
 #define RESCHEDULE_VECTOR	0xfc
 #define CALL_FUNCTION_VECTOR	0xfb
 
+#define MULTIRING_AUTO_LAST_VECTOR	0xfa
+#define MULTIRING_AUTO_FIRST_VECTOR	0xf1
+
 #define THERMAL_APIC_VECTOR	0xf0
 /*
  * Local APIC timer IRQ vector is on a different priority level,
@@ -37,26 +43,26 @@
 #define LOCAL_TIMER_VECTOR	0xef
 
 /*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
+ * First APIC vector available to drivers: (vectors 0x41-0xee)
+ * we start at 0x41 to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_DEVICE_VECTOR	0x41
 #define FIRST_SYSTEM_VECTOR	0xef
 
 #define TIMER_IRQ 0
 
 /*
- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+ * 16 8259A IRQ's, 192 potential APIC interrupt sources.
  * Right now the APIC is mostly only used for SMP.
  * 256 vectors is an architectural limit. (we can have
  * more than 256 devices theoretically, but they will
  * have to use shared interrupts)
  * Since vectors 0x00-0x1f are used/reserved for the CPU,
- * the usable vector space is 0x20-0xff (224 vectors)
+ * the usable vector space is 0x30-0xff (208 vectors)
  */
 #ifdef CONFIG_X86_IO_APIC
-#define NR_IRQS 224
+#define NR_IRQS 208
 #else
 #define NR_IRQS 16
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/math-emu/fpu_entry.c linux-2.5.44_multiring/arch/i386/math-emu/fpu_entry.c
--- linux-2.5.44/arch/i386/math-emu/fpu_entry.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/math-emu/fpu_entry.c	2002-10-27 00:44:03.000000000 +0200
@@ -171,7 +171,7 @@ asmlinkage void math_emulate(long arg)
       FPU_EIP += code_base = FPU_CS << 4;
       code_limit = code_base + 0xffff;  /* Assumes code_base <= 0xffff0000 */
     }
-  else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS )
+  else if ( (FPU_CS | 3) == USER_CS_RPL(3) && (FPU_DS | 3) == USER_DS_RPL(3) )
     {
       addr_modes.default_mode = 0;
     }
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/arch/i386/mm/fault.c linux-2.5.44_multiring/arch/i386/mm/fault.c
--- linux-2.5.44/arch/i386/mm/fault.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/arch/i386/mm/fault.c	2002-10-27 00:44:03.000000000 +0200
@@ -157,6 +157,10 @@ asmlinkage void do_page_fault(struct pt_
 
 	tsk = current;
 
+	/* User code at DPL 1 and 2 will also cause the U/S bit to be unset */
+	if(current->thread.multiring_mode && (regs->xcs & 3))
+		error_code |= 4;
+	
 	/*
 	 * We fault-in kernel-space virtual memory on-demand. The
 	 * 'reference' page table is init_mm.pgd.
@@ -270,6 +274,7 @@ bad_area:
 	up_read(&mm->mmap_sem);
 
 	/* User mode accesses just cause a SIGSEGV */
+	/* Note: F0 0F C7 C8 in DPL 1 or 2 will cause the if body to be executed (seems unavoidable) */
 	if (error_code & 4) {
 		tsk->thread.cr2 = address;
 		tsk->thread.error_code = error_code;
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/fs/exec.c linux-2.5.44_multiring/fs/exec.c
--- linux-2.5.44/fs/exec.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/fs/exec.c	2002-10-27 02:14:07.000000000 +0200
@@ -1021,7 +1021,11 @@ int do_execve(char * filename, char ** a
 	if (!bprm.mm)
 		goto out_file;
 
+#ifdef init_new_context_flags
+	retval = init_new_context_flags(current, bprm.mm, CLONE_EXEC);
+#else
 	retval = init_new_context(current, bprm.mm);
+#endif
 	if (retval < 0)
 		goto out_mm;
 
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/desc.h linux-2.5.44_multiring/include/asm-i386/desc.h
--- linux-2.5.44/include/asm-i386/desc.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/desc.h	2002-10-27 00:44:03.000000000 +0200
@@ -3,12 +3,16 @@
 
 #include <asm/ldt.h>
 #include <asm/segment.h>
+#include <asm/page.h>
+
+#define USER_CSDS_A (((__PAGE_OFFSET - 1) >> PAGE_SHIFT) & 0xffff)
+#define USER_CSDS_B(data, ring) (0x00c09200 | (((__PAGE_OFFSET - 1) >> PAGE_SHIFT) & 0xf0000) | ((!(data)) << 11) | ((ring) << 13))
 
 #ifndef __ASSEMBLY__
 
 #include <asm/mmu.h>
 
-extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
+extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES], idt_table[IDT_ENTRIES];
 
 struct Xgt_desc_struct {
 	unsigned short size;
@@ -61,7 +65,7 @@ static inline void set_ldt_desc(unsigned
 	((info)->seg_32bit << 22) | \
 	((info)->limit_in_pages << 23) | \
 	((info)->useable << 20) | \
-	0x7000)
+	0x1000 | (USER_RING << 13))
 
 #define LDT_empty(info) (\
 	(info)->base_addr	== 0	&& \
@@ -73,6 +77,35 @@ static inline void set_ldt_desc(unsigned
 	(info)->seg_not_present	== 1	&& \
 	(info)->useable		== 0	)
 
+extern int LDT_handle_over_page_offset(mm_context_t* ctx);
+
+static inline int LDT_handle_perm(struct user_desc* info, mm_context_t* ctx)
+{
+	unsigned limit;
+	unsigned maxlim;
+	if(info->base_addr >= __PAGE_OFFSET)
+		return LDT_handle_over_page_offset(ctx);
+	
+	limit = info->limit & 0xfffff;
+	if(info->limit_in_pages)
+		limit = (limit << PAGE_SHIFT) + (PAGE_SIZE - 1);
+
+	maxlim = (__PAGE_OFFSET - 1) - info->base_addr;
+	if(limit > maxlim)
+	{
+		if(maxlim <= 0xfffff)
+		{
+			info->limit = maxlim;
+			info->limit_in_pages = 0;			
+		}
+		else if(!(info->base_addr & ~PAGE_MASK))
+			info->limit = maxlim >> PAGE_SHIFT;
+		else
+			return LDT_handle_over_page_offset(ctx);
+	}
+	return 0;
+}
+
 #if TLS_SIZE != 24
 # error update this code.
 #endif
@@ -117,6 +150,17 @@ static inline void load_LDT(mm_context_t
 	put_cpu();
 }
 
+static inline unsigned get_user_ring(void)
+{
+	preempt_disable();
+	return unlikely(current->thread.multiring_mode) ? MULTIRING_USER_RING : USER_RING;
+}
+
+static inline void put_user_ring(void)
+{
+	preempt_enable();
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/fixmap.h linux-2.5.44_multiring/include/asm-i386/fixmap.h
--- linux-2.5.44/include/asm-i386/fixmap.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/fixmap.h	2002-10-27 00:44:03.000000000 +0200
@@ -48,6 +48,10 @@
  * future, say framebuffers for the console driver(s) could be
  * fix-mapped?
  */
+
+extern int __fix_idt_begin_should_have_been_optimized_away(void);
+extern int __fix_idt_end_should_have_been_optimized_away(void);
+
 enum fixed_addresses {
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
@@ -62,9 +66,15 @@ enum fixed_addresses {
 	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
 	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
 #endif
-#ifdef CONFIG_X86_F00F_BUG
-	FIX_F00F_IDT,	/* Virtual mapping for IDT */
+
+#if defined(CONFIG_X86_F00F_BUG) || defined(CONFIG_X86_HIGHIDT)
+	FIX_IDT_BEGIN, /* Virtual mapping for IDT */
+	FIX_IDT_END = FIX_IDT_BEGIN + NR_CPUS - 1,
+#else
+#define FIX_IDT_BEGIN __fix_idt_begin_should_have_been_optimized_away()
+#define FIX_IDT_END __fix_idt_end_should_have_been_optimized_away()	
 #endif
+
 #ifdef CONFIG_X86_CYCLONE
 	FIX_CYCLONE_TIMER, /*cyclone timer register*/
 #endif 
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/idt.h linux-2.5.44_multiring/include/asm-i386/idt.h
--- linux-2.5.44/include/asm-i386/idt.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/idt.h	2002-10-27 03:18:13.000000000 +0100
@@ -0,0 +1,236 @@
+/*
+ * linux/include/asm-i386/multiring.h: multiring IDT inline functions
+ *
+ * Copyright (C) 2002 Luca Barbieri <ldb@ldb.ods.org>
+ */
+
+#ifndef __i386_IDT_H
+#define __i386_IDT_H
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <asm/atomic.h>
+#include <linux/spinlock.h>
+
+#include <asm/desc.h>
+#include <asm/segment.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+#ifdef CONFIG_X86_HIGHIDT
+#define use_highidt 1
+#else
+#define use_highidt 0
+#endif
+
+#ifdef CONFIG_X86_F00F_BUG
+#define cpu_has_f00f_bug boot_cpu_data.f00f_bug
+#else
+#define cpu_has_f00f_bug 0
+#endif
+
+extern pte_t* idt_pte;
+extern unsigned idt_prot;
+extern pte_t idt_table_pte;
+
+/* access to idt_refcnt */
+static inline struct desc_struct* kmap_idt(mm_context_t* ctx)
+{
+	if(use_highidt)
+	{
+		if(!cpu_has_f00f_bug)
+		{
+			unsigned cpu = get_cpu();
+			return (struct desc_struct*)__fix_to_virt(FIX_IDT_BEGIN + cpu);
+		}
+		else
+		{
+			/* we need to kmap because the window is read-only */
+			return kmap(ctx->idt.page);
+		}
+	}
+	return ctx->idt.addr;	
+}
+
+static inline rwlock_t* idt_lock(struct desc_struct* idt)
+{
+	return (rwlock_t*)((char*)idt + IDT_SIZE);
+}
+
+/* read access */
+static inline struct desc_struct* kmap_read_idt(mm_context_t* ctx)
+{
+	struct desc_struct* idt = kmap_idt(ctx);
+	read_lock(idt_lock(idt));
+	return idt;
+}
+
+/* write access */
+static inline struct desc_struct* kmap_write_idt(mm_context_t* ctx)
+{
+	struct desc_struct* idt = kmap_idt(ctx);
+	write_lock(idt_lock(idt));
+	return idt;	
+}
+
+static inline struct desc_struct* kmap_read_idt_or_table(mm_context_t* ctx)
+{
+	if(current->thread.multiring_mode)
+		return kmap_read_idt(ctx);
+	else
+		return idt_table;
+}
+
+static inline void kunmap_idt(mm_context_t* ctx, struct desc_struct* idt)
+{
+	if(use_highidt)
+	{
+		if(!cpu_has_f00f_bug)
+			put_cpu();
+		else
+			kunmap(ctx->idt.page);
+	}
+}
+
+static inline void kunmap_read_idt(mm_context_t* ctx, struct desc_struct* idt)
+{
+	read_unlock(idt_lock(idt));
+	kunmap_idt(ctx, idt);
+}
+
+static inline void kunmap_write_idt(mm_context_t* ctx, struct desc_struct* idt)
+{
+	write_unlock(idt_lock(idt));
+	kunmap_idt(ctx, idt);
+}
+
+static inline void kunmap_read_idt_or_table(mm_context_t* ctx, struct desc_struct* idt)
+{
+	if(idt != idt_table)
+		return kunmap_read_idt(ctx, idt);
+}
+
+static inline void load_idt_table(unsigned cpu)
+{
+	if(use_highidt || cpu_has_f00f_bug)
+	{
+		set_pte(idt_pte - cpu, idt_table_pte);
+		__flush_tlb_one(__fix_to_virt(FIX_IDT_BEGIN + cpu));
+	}
+	else
+		__asm__ __volatile__("lidt %0": "=m" (idt_descr));
+}
+
+static inline void change_gdt_ring(unsigned cpu, unsigned ring)
+{
+	cpu_gdt_table[cpu][GDT_ENTRY_DEFAULT_USER_CS].b = USER_CSDS_B(0, ring);
+	cpu_gdt_table[cpu][GDT_ENTRY_DEFAULT_USER_DS].b = USER_CSDS_B(1, ring);
+}
+
+extern void multiring_init_task(task_t* tsk);
+
+static inline void load_IDT_nolock_inline(task_t* tsk, mm_context_t* ctx, unsigned cpu)
+{
+	if(!ctx->idt.opaque)
+	{
+		load_idt_table(cpu);
+		change_gdt_ring(cpu, 3);
+		return;
+	}
+
+	change_gdt_ring(cpu, MULTIRING_USER_RING);
+	if(use_highidt || cpu_has_f00f_bug)
+	{
+		set_pte(idt_pte - cpu, cpu_has_f00f_bug ? pfn_pte(__pa(ctx->idt.addr) >> PAGE_SHIFT, PAGE_KERNEL_RO) : mk_pte(ctx->idt.page, PAGE_KERNEL));
+		__flush_tlb_one(__fix_to_virt(FIX_IDT_BEGIN + cpu));
+	}
+	else
+	{
+		struct Xgt_desc_struct map_idt_descr;
+		map_idt_descr.size = IDT_SIZE - 1;
+		map_idt_descr.address = (unsigned long)ctx->idt.addr;
+		__asm__ __volatile__("lidt %0": "=m" (map_idt_descr));
+	}
+	if(unlikely(!tsk->thread.multiring_mode))
+	{
+		multiring_init_task(tsk);
+		tsk->thread.multiring_mode = 1;
+	}
+}
+
+static inline void load_IDT_inline(task_t* tsk, mm_context_t* ctx)
+{
+	unsigned cpu = get_cpu();
+	load_IDT_nolock_inline(tsk, ctx, cpu);
+	put_cpu();
+}
+
+extern void load_IDT_nolock(mm_context_t* ctx, unsigned cpu);
+
+static inline void load_IDT(mm_context_t* ctx)
+{
+	unsigned cpu = get_cpu();
+	load_IDT_nolock(ctx, cpu);
+	put_cpu();
+}
+
+static inline atomic_t* idt_refcnt(struct desc_struct* idt)
+{
+	return (atomic_t*)((char*)idt + IDT_SIZE + sizeof(spinlock_t));
+}
+
+static inline struct desc_struct* __alloc_idt(union idt* idtu)
+{
+	if(use_highidt)
+	{
+		/* Use high memory */
+		idtu->page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+		return (struct desc_struct*)kmap(idtu->page);
+	}
+	else
+	{
+		/* TODO: use an aligned 2KB allocator instead */
+		return idtu->addr = (struct desc_struct*)__get_free_page(GFP_KERNEL);
+	}
+}
+
+static inline struct desc_struct* alloc_idt(union idt* idtu)
+{
+	struct desc_struct* idt = __alloc_idt(idtu);
+	if(idt)
+	{
+		*idt_lock(idt) = RW_LOCK_UNLOCKED;
+		atomic_set(idt_refcnt(idt), 1);
+	}
+	return idt;
+}
+
+static inline void kunmap_new_idt(union idt* idtu, struct desc_struct* idt)
+{
+	if(use_highidt)
+		kunmap(idtu->page);
+}
+
+static inline void __free_idt(mm_context_t* ctx)
+{
+	if(use_highidt)
+		__free_page(ctx->idt.page);
+	else
+		free_page((unsigned long)ctx->idt.addr);
+}
+
+static inline void free_idt(mm_context_t* ctx)
+{
+	struct desc_struct* idt = kmap_idt(ctx);
+	int free = atomic_dec_and_test(idt_refcnt(idt));
+	kunmap_idt(ctx, idt);
+	if(free)
+		__free_idt(ctx);
+}
+
+#endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/ldt.h linux-2.5.44_multiring/include/asm-i386/ldt.h
--- linux-2.5.44/include/asm-i386/ldt.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/ldt.h	2002-10-27 00:44:03.000000000 +0200
@@ -22,6 +22,9 @@ struct user_desc {
 	unsigned int  limit_in_pages:1;
 	unsigned int  seg_not_present:1;
 	unsigned int  useable:1;
+
+	/* has effect only in multiring mode, but is returned in any mode */
+	unsigned int  dpl:2; 
 };
 
 #define MODIFY_LDT_CONTENTS_DATA	0
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/mmu_context.h linux-2.5.44_multiring/include/asm-i386/mmu_context.h
--- linux-2.5.44/include/asm-i386/mmu_context.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/mmu_context.h	2002-10-27 03:13:34.000000000 +0100
@@ -6,12 +6,15 @@
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/idt.h>
 
 /*
  * possibly do the LDT unload here?
  */
 #define destroy_context(mm)		do { } while(0)
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+int init_new_context_flags(struct task_struct *tsk, struct mm_struct *mm, unsigned flags);
+#define init_new_context_flags init_new_context_flags
+#define init_new_context(tsk, mm) init_new_context_flags(tsk, mm, 0)
 
 #ifdef CONFIG_SMP
 
@@ -45,6 +48,9 @@ static inline void switch_mm(struct mm_s
 		 */
 		if (unlikely(prev->context.ldt != next->context.ldt))
 			load_LDT_nolock(&next->context, cpu);
+
+		if (unlikely(prev->context.idt.opaque != next->context.idt.opaque))
+			load_IDT_nolock_inline(tsk, &next->context, cpu);
 	}
 #ifdef CONFIG_SMP
 	else {
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/mmu.h linux-2.5.44_multiring/include/asm-i386/mmu.h
--- linux-2.5.44/include/asm-i386/mmu.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/mmu.h	2002-10-27 00:44:03.000000000 +0200
@@ -7,10 +7,20 @@
  *
  * cpu_vm_mask is used to optimize ldt flushing.
  */
+
+union idt
+{
+	struct desc_struct* addr;
+	struct page* page;
+	unsigned long opaque;
+};
+
 typedef struct { 
 	int size;
 	struct semaphore sem;
 	void *ldt;
+	union idt idt;
+	unsigned char bad_segments;
 } mm_context_t;
 
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/multiring.h linux-2.5.44_multiring/include/asm-i386/multiring.h
--- linux-2.5.44/include/asm-i386/multiring.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/multiring.h	2002-10-27 00:44:03.000000000 +0200
@@ -0,0 +1,194 @@
+/*
+ * linux/include/asm-i386/multiring.h: header for multiple privilege rings support (available to user-mode)
+ *
+ * Copyright (C) 2002 Luca Barbieri <ldb@ldb.ods.org>
+ */
+
+#ifndef __i386_MULTIRING_H
+#define __i386_MULTIRING_H
+
+#define MULTIRING_CHECK    0
+
+#define MULTIRING_GET_ESPSS 1
+#define MULTIRING_SET_ESPSS 2
+
+#define MULTIRING_GET      3
+#define MULTIRING_GET_RANGE 4
+
+#define MULTIRING_ELEVATE  5
+#define MULTIRING_SET      6
+#define MULTIRING_COPY     7
+#define MULTIRING_LAST_OP  7
+
+#define MULTIRING_VEC_FREE ((unsigned char)~0)
+
+#ifdef __KERNEL__
+#define multiring_gate desc_struct
+#else
+struct multiring_gate
+{
+	unsigned long a;
+	unsigned long b;	
+};
+#endif
+
+#ifndef __KERNEL__
+#ifndef MULTIRING_NO_SYSCALLS
+#ifndef _syscall1
+#include <asm/unistd.h>
+#endif
+
+#define __NR_multiring0 __NR_multiring
+#define __NR_multiring1 __NR_multiring
+#define __NR_multiring2 __NR_multiring
+#define __NR_multiring3 __NR_multiring
+
+_syscall1(int, multiring0, unsigned, op);
+_syscall2(int, multiring1, unsigned, op, unsigned long, arg1);
+_syscall3(int, multiring2, unsigned, op, unsigned long, arg1, unsigned long, arg2);
+_syscall4(int, multiring3, unsigned, op, unsigned long, arg1, unsigned long, arg2, unsigned long, arg3);
+#endif
+
+#ifndef MULTIRING_NO_HELPERS
+/*
+  Check whether the program is in multiring mode.
+
+  Return value:
+  0: multiring mode
+  1: normal mode
+  -1/EPERM: normal mode; can't enter multiring mode due to a bad segment
+*/
+static inline int multiring_check()
+{
+	return multiring0(MULTIRING_CHECK);
+}
+
+/* Enters multiring mode.
+   This fails if you have previously set up a "bad segment" with modify_ldt, set_thread_area or CLONE_SETTLS.
+   A bad segment is a segment that either starts in the kernel memory region or has a limit expressed in pages, with a value that causes it to contain the kernel region and with a non-page-aligned base address.
+
+   This will cause the process to get a private IDT that starts as a copy of the global one, but with the SYSCALL_VECTOR DPL set to 1.
+   Multiring processes also have the DPL on the GDT CS and DS descriptors set to 1.
+   Upon return, in all threads, cs/ds/es/ss/fs/gs selectors pointing to the default CS/DS will be changed to have RPL=1.
+
+   Return value:
+   0: success
+   -1/EPERM: can't enter multiring mode due to a bad segment
+   -1/ENOMEM: couldn't allocate the IDT
+*/
+static inline int multiring_elevate()
+{
+	return multiring0(MULTIRING_ELEVATE);
+}
+
+/*
+  Return TSS ESP/SS value for a privilege ring
+  
+  Parameters:
+  ring: privilege ring whose tss esp/ss you want to get
+  esp: pointer to returned tss esp value
+  ss: pointer to returned tss ss value
+*/
+static inline int multiring_get_espss(unsigned ring, unsigned* esp, unsigned* ss)
+{
+	return multiring3(MULTIRING_GET_ESPSS, ring, (unsigned long)esp, (unsigned long)ss);
+}
+
+/*
+  Set TSS ESP/SS value for a privilege ring
+  Note: while multiring mode is currently not needed to do this, you shouldn't rely on this.
+  
+  Parameters:
+  ring: privilege ring whose tss esp/ss you want to set
+  esp: new tss esp value
+  ss: new tss ss value - must have RPL == ring
+*/
+static inline int multiring_set_espss(unsigned ring, unsigned esp, unsigned ss)
+{
+	return multiring3(MULTIRING_SET_ESPSS, ring, esp, ss);
+}
+
+/*
+  Get a single interrupt gate.
+
+  Parameters:
+  vec: vector number
+  gate: pointer to returned multiring_gate
+*/
+static inline int multiring_get(unsigned vec, struct multiring_gate* gate)
+{
+	return multiring2(MULTIRING_GET, vec, (unsigned long)gate);
+}
+
+/*
+  Get a range of interrupt gates.
+
+  Parameters:
+  first: first vector number
+  last: last vector numer
+  gates: pointer to returned multiring_gate structs (size must be >= (last - first + 1) * sizeof(struct multiring_gate))
+*/
+static inline int multiring_get_range(unsigned first, unsigned last, struct multiring_gate* gates)
+{
+	return multiring3(MULTIRING_GET_RANGE, first, last, (unsigned long)gates);
+}
+
+/*
+  Set an interrupt gate.
+
+  Parameters:
+  vec: vector number or MULTIRING_VEC_FREE to get a free one (or ENOSPC if none found)
+  a: first 32-bit word of interrupt gate
+  b: second 32-bit word of interrupt gate
+
+  Return value:
+  >= 0: success, return value is vector number
+  -1/EPERM: you tried to set an unmodifiable vector or to create a gate to a non-syscall RPL 0 address or there was an another permission denied error
+  -1/ENXIO: you weren't in multiring mode  
+  -1/EINVAL: you tried to create a task/interrupt gate, a DPL 0 gate, a gate with reserved regions with wrong value, or something else considered invalid/not supported
+  -1/ENOSPC: you specified MULTIRING_VEC_FREE but there was no available free vector
+*/
+static inline int multiring_set(unsigned vec, unsigned long a, unsigned long b)
+{
+	return multiring3(MULTIRING_SET, vec, a, b);
+}
+
+/* like multiring_set with vec=MULTIRING_VEC_FREE */
+static inline int multiring_set_free(unsigned long a, unsigned long b)
+{
+	return multiring_set(MULTIRING_VEC_FREE, a, b);
+}
+
+/* like multiring_set with a=0 b=0 */
+static inline int multiring_free(unsigned vec)
+{
+	return multiring_set(vec, 0, 0);
+}
+
+/*
+  Set an interrupt gate based on another one
+  
+  Parameters:
+  vec: vector number or MULTIRING_VEC_FREE to get a free one (or ENOSPC if none found)
+  from: vector number to copy from
+
+  Return value:
+  >= 0: success, return value is vector number
+  -1/ENXIO: you weren't in multiring mode  
+  -1/EPERM: you tried to set an unmodifiable vector or to create a gate to a non-syscall RPL 0 address or there was an another permission denied error
+  -1/ENOSPC: you specified MULTIRING_VEC_FREE but there was no available free vector
+*/
+static inline int multiring_copy(unsigned vec, unsigned from)
+{
+	return multiring2(MULTIRING_COPY, vec, from);
+}
+
+/* like multiring_copy with vec=MULTIRING_VEC_FREE */
+static inline int multiring_copy_free(unsigned from)
+{
+	return multiring_copy(MULTIRING_VEC_FREE, from);
+}
+
+#endif
+#endif
+#endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/processor.h linux-2.5.44_multiring/include/asm-i386/processor.h
--- linux-2.5.44/include/asm-i386/processor.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/processor.h	2002-10-27 00:44:04.000000000 +0200
@@ -332,14 +332,17 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
+struct espss
+{
+	unsigned long esp;
+	unsigned long ss;
+};
+
 struct tss_struct {
 	unsigned short	back_link,__blh;
 	unsigned long	esp0;
 	unsigned short	ss0,__ss0h;
-	unsigned long	esp1;
-	unsigned short	ss1,__ss1h;
-	unsigned long	esp2;
-	unsigned short	ss2,__ss2h;
+	struct espss espss12[2];
 	unsigned long	__cr3;
 	unsigned long	eip;
 	unsigned long	eflags;
@@ -367,10 +370,12 @@ struct thread_struct {
 /* cached TLS descriptors. */
 	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
 	unsigned long	esp0;
+	struct espss espss12[2];
 	unsigned long	eip;
 	unsigned long	esp;
 	unsigned long	fs;
 	unsigned long	gs;
+	unsigned char	multiring_mode;	
 /* Hardware debugging registers */
 	unsigned long	debugreg[8];  /* %%db0-7 debug registers */
 /* fault info */
@@ -388,7 +393,8 @@ struct thread_struct {
 #define INIT_THREAD  {						\
 	{ { 0, 0 } , },						\
 	0,							\
-	0, 0, 0, 0, 						\
+	{ {0, 0}, {0, 0} },					\
+	0, 0, 0, 0, 0, 						\
 	{ [0 ... 7] = 0 },	/* debugging registers */	\
 	0, 0, 0,						\
 	{ { 0, }, },		/* 387 state */			\
@@ -400,7 +406,7 @@ struct thread_struct {
 	0,0, /* back_link, __blh */				\
 	sizeof(init_stack) + (long) &init_stack, /* esp0 */	\
 	__KERNEL_DS, 0, /* ss0 */				\
-	0,0,0,0,0,0, /* stack1, stack2 */			\
+	{ {0, 0}, {0, 0} }, /* stack1, stack2 */			\
 	0, /* cr3 */						\
 	0,0, /* eip,eflags */					\
 	0,0,0,0, /* eax,ecx,edx,ebx */				\
@@ -415,10 +421,10 @@ struct thread_struct {
 #define start_thread(regs, new_eip, new_esp) do {		\
 	__asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));	\
 	set_fs(USER_DS);					\
-	regs->xds = __USER_DS;					\
-	regs->xes = __USER_DS;					\
-	regs->xss = __USER_DS;					\
-	regs->xcs = __USER_CS;					\
+	regs->xds = USER_DS_RPL(USER_RING);					\
+	regs->xes = USER_DS_RPL(USER_RING);					\
+	regs->xss = USER_DS_RPL(USER_RING);					\
+	regs->xcs = USER_CS_RPL(USER_RING);					\
 	regs->eip = new_eip;					\
 	regs->esp = new_esp;					\
 } while (0)
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/segment.h linux-2.5.44_multiring/include/asm-i386/segment.h
--- linux-2.5.44/include/asm-i386/segment.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/segment.h	2002-10-27 00:44:04.000000000 +0200
@@ -1,6 +1,12 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
+/* The default user privilege level */
+#define USER_RING 3
+
+/* The multiring most privileged user level */
+#define MULTIRING_USER_RING 1
+
 /*
  * The layout of the per-CPU GDT under Linux:
  *
@@ -43,10 +49,10 @@
 #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
 
 #define GDT_ENTRY_DEFAULT_USER_CS	4
-#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)
+#define USER_CS_RPL(ring) (GDT_ENTRY_DEFAULT_USER_CS * 8 + (ring))
 
 #define GDT_ENTRY_DEFAULT_USER_DS	5
-#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)
+#define USER_DS_RPL(ring) (GDT_ENTRY_DEFAULT_USER_DS * 8 + (ring))
 
 #define GDT_ENTRY_KERNEL_BASE	12
 
@@ -76,4 +82,6 @@
  */
 #define IDT_ENTRIES 256
 
+#define IDT_SIZE (IDT_ENTRIES * 8)
+
 #endif
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/system.h linux-2.5.44_multiring/include/asm-i386/system.h
--- linux-2.5.44/include/asm-i386/system.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/system.h	2002-10-27 00:44:04.000000000 +0200
@@ -95,6 +95,12 @@ static inline unsigned long _get_base(ch
 		: :"m" (*(unsigned int *)&(value)))
 
 /*
+ * Save a segment.
+ */
+#define savesegment(seg,value) \
+	asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+
+/*
  * Clear and set 'TS' bit respectively
  */
 #define clts() __asm__ __volatile__ ("clts")
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/asm-i386/unistd.h linux-2.5.44_multiring/include/asm-i386/unistd.h
--- linux-2.5.44/include/asm-i386/unistd.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/asm-i386/unistd.h	2002-10-27 00:44:04.000000000 +0200
@@ -258,6 +258,7 @@
 #define __NR_free_hugepages	251
 #define __NR_exit_group		252
 #define __NR_lookup_dcookie	253
+#define __NR_multiring		254
   
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/include/linux/sched.h linux-2.5.44_multiring/include/linux/sched.h
--- linux-2.5.44/include/linux/sched.h	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/include/linux/sched.h	2002-10-27 02:36:47.000000000 +0200
@@ -51,6 +51,14 @@ struct exec_domain;
 #define CLONE_SETTID	0x00100000	/* write the TID back to userspace */
 #define CLONE_CLEARTID	0x00200000	/* clear the userspace TID */
 #define CLONE_DETACHED	0x00400000	/* parent wants no child-exit signal */
+#ifdef __i386__
+#define CLONE_IDT	0x00800000	/* set if IDT is shared between processes (note: CLONE_VM implies CLONE_IDT) */
+#define CLONE_CLEAR_IDT	0x01000000	/* set to clear the IDT */
+#define CLONE_EXEC CLONE_CLEAR_IDT
+#else
+#define CLONE_EXEC 0
+#endif
+
 
 /*
  * List of flags we want to share for kernel threads,
diff --exclude-from=/home/ldb/src/linux-exclude -urNdp linux-2.5.44/kernel/fork.c linux-2.5.44_multiring/kernel/fork.c
--- linux-2.5.44/kernel/fork.c	2002-10-27 02:38:39.000000000 +0100
+++ linux-2.5.44_multiring/kernel/fork.c	2002-10-27 00:44:04.000000000 +0200
@@ -435,7 +435,11 @@ static int copy_mm(unsigned long clone_f
 	if (!mm_init(mm))
 		goto fail_nomem;
 
-	if (init_new_context(tsk,mm))
+#ifdef init_new_context_flags
+	if (init_new_context_flags(tsk, mm, clone_flags))
+#else
+	if (init_new_context(tsk, mm))
+#endif		
 		goto free_pt;
 
 	down_write(&oldmm->mmap_sem);


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [RFC][PATCHSET 11/24] add support for PC-9800 architecture (input)
From: Osamu Tomita @ 2002-10-27  2:36 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: LKML, Alan Cox

This is a part 11/24 of patchset for add support NEC PC-9800 architecture,
against 2.5.44.

Thanks for many comments.
I've merged input(11/25) and keyboard(13/25) patch.
In this patch, I don't change input.h defkeymap.c defkeymap.map.
I removed kana support for default. I'll load another keymaps for kana
support.
I added codes into new driver(98kbd.c) to emulate US101 keyboard.

I can't find interface module for xtkbd.c to serio.c. So I write new
module based on i8042.c.
In defkeymaps, KEY_KPEQUAL and KEY_KPCOMMA seems odd. Please fix them.

Summary:
 input modules
  - add new driver for PC-9800 standard keyboard and mouse.
  - add few changes for PC-9800 hardware spec.

diffstat:
 drivers/char/keyboard.c          |    4 
 drivers/input/keyboard/98kbd.c   |  356 +++++++++++++++++++++++++++++++++++++++
 drivers/input/keyboard/Config.in |    4 
 drivers/input/keyboard/Makefile  |    1 
 drivers/input/misc/pcspkr.c      |   24 ++
 drivers/input/mouse/98busmouse.c |  201 ++++++++++++++++++++++
 drivers/input/mouse/Config.in    |    3 
 drivers/input/mouse/Makefile     |    1 
 drivers/input/serio/98kbd-io.c   |  181 +++++++++++++++++++
 drivers/input/serio/Config.in    |    3 
 drivers/input/serio/Makefile     |    1 
 include/linux/kbd_kern.h         |    5 
 include/linux/keyboard.h         |    1 
 13 files changed, 783 insertions(+), 2 deletions(-)

patch:
diff -urN linux/drivers/input/keyboard/Config.in linux98/drivers/input/keyboard/Config.in
--- linux/drivers/input/keyboard/Config.in	Sat Oct 12 13:22:45 2002
+++ linux98/drivers/input/keyboard/Config.in	Sun Oct 13 11:29:55 2002
@@ -9,6 +9,10 @@
 dep_tristate '  XT Keyboard support' CONFIG_KEYBOARD_XTKBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
 dep_tristate '  Newton keyboard' CONFIG_KEYBOARD_NEWTON $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
 
+if [ "$CONFIG_PC9800" = "y" ]; then
+   dep_tristate '  NEC PC-9801 keyboard support' CONFIG_KEYBOARD_98KBD $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_SERIO
+fi
+
 if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
    dep_tristate '  Maple bus keyboard support' CONFIG_KEYBOARD_MAPLE $CONFIG_INPUT $CONFIG_INPUT_KEYBOARD $CONFIG_MAPLE
 fi
diff -urN linux/drivers/input/keyboard/Makefile linux98/drivers/input/keyboard/Makefile
--- linux/drivers/input/keyboard/Makefile	Sat Oct 12 13:21:42 2002
+++ linux98/drivers/input/keyboard/Makefile	Sun Oct 13 11:27:15 2002
@@ -10,6 +10,7 @@
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
+obj-$(CONFIG_KEYBOARD_98KBD)		+= 98kbd.o
 
 # The global Rules.make.
 
diff -urN linux/drivers/input/keyboard/98kbd.c linux98/drivers/input/keyboard/98kbd.c
--- linux/drivers/input/keyboard/98kbd.c	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/input/keyboard/98kbd.c	Sun Oct 27 07:45:43 2002
@@ -0,0 +1,356 @@
+/*
+ *  drivers/input/keyboard/98kbd.c
+ *
+ *  PC-9801 keyboard driver for Linux
+ *
+ *    Based on atkbd.c and xtkbd.c written by Vojtech Pavlik
+ *
+ *  Copyright (c) 2002 Osamu Tomita
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+
+#include <asm/io.h>
+#include <asm/pc9800.h>
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_DESCRIPTION("PC-9801 keyboard driver");
+MODULE_LICENSE("GPL");
+
+#define KBD98_KEY	0x7f
+#define KBD98_RELEASE	0x80
+
+static unsigned char kbd98_keycode[256] = {	 
+	  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 43, 14, 15,
+	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 41, 26, 28, 30, 31, 32,
+	 33, 34, 35, 36, 37, 38, 39, 40, 27, 44, 45, 46, 47, 48, 49, 50,
+	 51, 52, 53, 12, 57,184,109,104,110,111,103,105,106,108,102,107,
+	 74, 98, 71, 72, 73, 55, 75, 76, 77, 78, 79, 80, 81,117, 82,124,
+	 83,185, 87, 88, 85, 89, 90,  0,  0,  0,  0,  0,  0,  0,102,  0,
+	 99,133, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,  0,  0,  0,  0,
+	 54, 58, 42, 56, 29
+};
+
+struct jis_kbd_conv {
+	unsigned char scancode;
+	struct {
+		unsigned char shift;
+		unsigned char keycode;
+	} emul[2];
+};
+
+static struct jis_kbd_conv kbd98_jis[] = {
+	{0x02, {{0,   3}, {1,  40}}},
+	{0x06, {{0,   7}, {1,   8}}},
+	{0x07, {{0,   8}, {0,  40}}},
+	{0x08, {{0,   9}, {1,  10}}},
+	{0x09, {{0,  10}, {1,  11}}},
+	{0x0a, {{0,  11}, {1, 255}}},
+	{0x0b, {{0,  12}, {0,  13}}},
+	{0x0c, {{1,   7}, {0,  41}}},
+	{0x1a, {{1,   3}, {1,  41}}},
+	{0x26, {{0,  39}, {1,  13}}},
+	{0x27, {{1,  39}, {1,   9}}},
+	{0x33, {{0, 255}, {1,  12}}},
+	{0xff, {{0, 255}, {1, 255}}}	/* terminater */
+};
+
+#define KBD98_CMD_SETEXKEY	0x1095	/* Enable/Disable Windows, Appli key */
+#define KBD98_CMD_SETRATE	0x109c	/* Set typematic rate */
+#define KBD98_CMD_SETLEDS	0x109d	/* Set keyboard leds */
+#define KBD98_CMD_GETLEDS	0x119d	/* Get keyboard leds */
+#define KBD98_CMD_GETID		0x019f
+
+#define KBD98_RET_ACK		0xfa
+#define KBD98_RET_NAK		0xfc	/* Command NACK, send the cmd again */
+
+#define KBD98_KEY_JIS_EMUL	254
+#define KBD98_KEY_NULL		255
+
+static char *kbd98_name = "PC-9801 Keyboard";
+
+struct kbd98 {
+	unsigned char keycode[256];
+	struct input_dev dev;
+	struct serio *serio;
+	char phys[32];
+	unsigned char cmdbuf[4];
+	unsigned char cmdcnt;
+	signed char ack;
+	unsigned char shift;
+	struct jis_kbd_conv jis[16];
+};
+
+void kbd98_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+	struct kbd98 *kbd98 = serio->private;
+	unsigned char scancode, keycode;
+	int press, i;
+
+	switch (data) {
+		case KBD98_RET_ACK:
+			kbd98->ack = 1;
+			return;
+		case KBD98_RET_NAK:
+			kbd98->ack = -1;
+			return;
+	}
+
+	if (kbd98->cmdcnt) {
+		kbd98->cmdbuf[--kbd98->cmdcnt] = data;
+		return;
+	}
+
+	scancode = data & KBD98_KEY;
+	keycode = kbd98->keycode[scancode];
+	press = !(data & KBD98_RELEASE);
+	if (keycode == KEY_RIGHTSHIFT)
+		kbd98->shift = press;
+
+	switch (keycode) {
+		case KEY_2:
+		case KEY_6:
+		case KEY_7:
+		case KEY_8:
+		case KEY_9:
+		case KEY_0:
+		case KEY_MINUS:
+		case KEY_EQUAL:
+		case KEY_GRAVE:
+		case KEY_SEMICOLON:
+		case KEY_APOSTROPHE:
+			/* emulation: JIS keyboard to US101 keyboard */
+			i = 0;
+			while (kbd98->jis[i].scancode != 0xff) {
+				if (scancode == kbd98->jis[i].scancode)
+					break;
+				i ++;
+			}
+
+			keycode = kbd98->jis[i].emul[kbd98->shift].keycode;
+			if (keycode == KBD98_KEY_NULL)
+				return;
+
+			if (kbd98->jis[i].emul[kbd98->shift].shift != kbd98->shift && press) {
+				input_report_key(&kbd98->dev, KEY_RIGHTSHIFT, !(kbd98->shift));
+			}
+
+			input_report_key(&kbd98->dev, keycode, press);
+			if (kbd98->jis[i].emul[kbd98->shift].shift != kbd98->shift && !press) {
+				input_report_key(&kbd98->dev, KEY_RIGHTSHIFT, kbd98->shift);
+			}
+
+			input_sync(&kbd98->dev);
+			return;
+
+		case KBD98_KEY_NULL:
+			return;
+
+		case 0:
+			printk(KERN_WARNING "kbd98.c: Unknown key (scancode %#x) %s.\n",
+				data & KBD98_KEY, data & KBD98_RELEASE ? "released" : "pressed");
+			return;
+
+		default:
+			input_report_key(&kbd98->dev, keycode, press);
+			input_sync(&kbd98->dev);
+		}
+}
+
+/*
+ * kbd98_sendbyte() sends a byte to the keyboard, and waits for
+ * acknowledge. It doesn't handle resends according to the keyboard
+ * protocol specs, because if these are needed, the keyboard needs
+ * replacement anyway, and they only make a mess in the protocol.
+ */
+
+static int kbd98_sendbyte(struct kbd98 *kbd98, unsigned char byte)
+{
+	int timeout = 10000; /* 100 msec */
+	kbd98->ack = 0;
+
+	if (serio_write(kbd98->serio, byte))
+		return -1;
+
+	while (!kbd98->ack && timeout--) udelay(10);
+
+	return -(kbd98->ack <= 0);
+}
+
+/*
+ * kbd98_command() sends a command, and its parameters to the keyboard,
+ * then waits for the response and puts it in the param array.
+ */
+
+static int kbd98_command(struct kbd98 *kbd98, unsigned char *param, int command)
+{
+	int timeout = 50000; /* 500 msec */
+	int send = (command >> 12) & 0xf;
+	int receive = (command >> 8) & 0xf;
+	int i;
+
+	kbd98->cmdcnt = receive;
+	
+	if (command & 0xff)
+		if (kbd98_sendbyte(kbd98, command & 0xff))
+			return (kbd98->cmdcnt = 0) - 1;
+
+	for (i = 0; i < send; i++)
+		if (kbd98_sendbyte(kbd98, param[i]))
+			return (kbd98->cmdcnt = 0) - 1;
+
+	while (kbd98->cmdcnt && timeout--) udelay(10);
+
+	if (param)
+		for (i = 0; i < receive; i++)
+			param[i] = kbd98->cmdbuf[(receive - 1) - i];
+
+	if (kbd98->cmdcnt) 
+		return (kbd98->cmdcnt = 0) - 1;
+
+	return 0;
+}
+
+/*
+ * Event callback from the input module. Events that change the state of
+ * the hardware are processed here.
+ */
+
+static int kbd98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	struct kbd98 *kbd98 = dev->private;
+	char param[2];
+
+	switch (type) {
+
+		case EV_LED:
+
+			if (__PC9800SCA_TEST_BIT(0x481, 3)) {
+				/* 98note with Num Lock key */
+				/* keep Num Lock status     */
+				*param = 0x60;
+				if (kbd98_command(kbd98, param,
+							KBD98_CMD_GETLEDS))
+					printk(KERN_DEBUG
+						"kbd98: Get keyboard LED"
+						" status Error\n");
+
+				*param &= 1;
+			} else {
+				/* desktop PC-9801 */
+				*param = 1;	/* Allways set Num Lock */
+			}
+
+			*param |= 0x70
+			       | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0)
+			       | (test_bit(LED_KANA,    dev->led) ? 8 : 0);
+		        kbd98_command(kbd98, param, KBD98_CMD_SETLEDS);
+
+			return 0;
+	}
+
+	return -1;
+}
+
+void kbd98_connect(struct serio *serio, struct serio_dev *dev)
+{
+	struct kbd98 *kbd98;
+	int i;
+
+	if ((serio->type & SERIO_TYPE) != SERIO_PC9800)
+		return;
+
+	if (!(kbd98 = kmalloc(sizeof(struct kbd98), GFP_KERNEL)))
+		return;
+
+	memset(kbd98, 0, sizeof(struct kbd98));
+	
+	kbd98->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+	kbd98->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_KANA);
+
+	kbd98->serio = serio;
+
+	init_input_dev(&kbd98->dev);
+	kbd98->dev.keycode = kbd98->keycode;
+	kbd98->dev.keycodesize = sizeof(unsigned char);
+	kbd98->dev.keycodemax = ARRAY_SIZE(kbd98_keycode);
+	kbd98->dev.event = kbd98_event;
+	kbd98->dev.private = kbd98;
+
+	serio->private = kbd98;
+
+	if (serio_open(serio, dev)) {
+		kfree(kbd98);
+		return;
+	}
+
+	memcpy(kbd98->jis, kbd98_jis, sizeof(kbd98_jis));
+	memcpy(kbd98->keycode, kbd98_keycode, sizeof(kbd98->keycode));
+	for (i = 0; i < 255; i++)
+		set_bit(kbd98->keycode[i], kbd98->dev.keybit);
+	clear_bit(0, kbd98->dev.keybit);
+
+	sprintf(kbd98->phys, "%s/input0", serio->phys);
+
+	kbd98->dev.name = kbd98_name;
+	kbd98->dev.phys = kbd98->phys;
+	kbd98->dev.id.bustype = BUS_XTKBD;
+	kbd98->dev.id.vendor = 0x0002;
+	kbd98->dev.id.product = 0x0001;
+	kbd98->dev.id.version = 0x0100;
+
+	input_register_device(&kbd98->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", kbd98_name, serio->phys);
+}
+
+void kbd98_disconnect(struct serio *serio)
+{
+	struct kbd98 *kbd98 = serio->private;
+	input_unregister_device(&kbd98->dev);
+	serio_close(serio);
+	kfree(kbd98);
+}
+
+struct serio_dev kbd98_dev = {
+	.interrupt =	kbd98_interrupt,
+	.connect =	kbd98_connect,
+	.disconnect =	kbd98_disconnect
+};
+
+int __init kbd98_init(void)
+{
+	serio_register_device(&kbd98_dev);
+	return 0;
+}
+
+void __exit kbd98_exit(void)
+{
+	serio_unregister_device(&kbd98_dev);
+}
+
+module_init(kbd98_init);
+module_exit(kbd98_exit);
diff -urN linux/drivers/input/misc/pcspkr.c linux98/drivers/input/misc/pcspkr.c
--- linux/drivers/input/misc/pcspkr.c	Mon Sep 16 11:18:31 2002
+++ linux98/drivers/input/misc/pcspkr.c	Mon Sep 16 16:04:05 2002
@@ -12,6 +12,7 @@
  * the Free Software Foundation
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -23,7 +24,11 @@
 MODULE_LICENSE("GPL");
 
 static char pcspkr_name[] = "PC Speaker";
+#ifndef CONFIG_PC9800
 static char pcspkr_phys[] = "isa0061/input0";
+#else
+static char pcspkr_phys[] = "isa3fdb/input0";
+#endif
 static struct input_dev pcspkr_dev;
 
 spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED;
@@ -43,11 +48,16 @@
 	} 
 
 	if (value > 20 && value < 32767)
+#ifndef CONFIG_PC9800
 		count = 1193182 / value;
+#else
+		count = CLOCK_TICK_RATE / value;
+#endif
 	
 	spin_lock_irqsave(&i8253_beep_lock, flags);
 
 	if (count) {
+#ifndef CONFIG_PC9800
 		/* enable counter 2 */
 		outb_p(inb_p(0x61) | 3, 0x61);
 		/* set command for counter 2, 2 byte write */
@@ -55,9 +65,23 @@
 		/* select desired HZ */
 		outb_p(count & 0xff, 0x42);
 		outb((count >> 8) & 0xff, 0x42);
+#else /* CONFIG_PC9800 */
+		outb(0x76, 0x3fdf);
+		outb(0, 0x5f);
+		outb(count & 0xff, 0x3fdb);
+		outb(0, 0x5f);
+		outb((count >> 8) & 0xff, 0x3fdb);
+		/* beep on */
+		outb(6, 0x37);
+#endif /* !CONFIG_PC9800 */
 	} else {
 		/* disable counter 2 */
+#ifndef CONFIG_PC9800
 		outb(inb_p(0x61) & 0xFC, 0x61);
+#else
+		/* beep off */
+		outb(7, 0x37);
+#endif
 	}
 
 	spin_unlock_irqrestore(&i8253_beep_lock, flags);
diff -urN linux/drivers/input/mouse/98busmouse.c linux98/drivers/input/mouse/98busmouse.c
--- linux/drivers/input/mouse/98busmouse.c	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/input/mouse/98busmouse.c	Sat Oct 26 18:36:15 2002
@@ -0,0 +1,201 @@
+/*
+ *
+ *  Copyright (c) 2002 Osamu Tomita
+ *
+ *  Based on the work of:
+ *	James Banks		Matthew Dillon
+ *	David Giller		Nathan Laredo
+ *	Linus Torvalds		Johan Myreen
+ *	Cliff Matthews		Philip Blundell
+ *	Russell King		Vojtech Pavlik
+ */
+
+/*
+ * NEC PC-9801 Bus Mouse Driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ */
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/input.h>
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_DESCRIPTION("PC-9801 busmouse driver");
+MODULE_LICENSE("GPL");
+
+#define	PC98BM_BASE		0x7fd9
+#define	PC98BM_DATA_PORT	PC98BM_BASE + 0
+/*	PC98BM_SIGNATURE_PORT	does not exist */
+#define	PC98BM_CONTROL_PORT	PC98BM_BASE + 4
+/*	PC98BM_INTERRUPT_PORT	does not exist */
+#define	PC98BM_CONFIG_PORT	PC98BM_BASE + 6
+
+#define	PC98BM_ENABLE_IRQ	0x00
+#define	PC98BM_DISABLE_IRQ	0x10
+#define	PC98BM_READ_X_LOW	0x80
+#define	PC98BM_READ_X_HIGH	0xa0
+#define	PC98BM_READ_Y_LOW	0xc0
+#define	PC98BM_READ_Y_HIGH	0xe0
+
+#define PC98BM_DEFAULT_MODE	0x93
+/*	PC98BM_CONFIG_BYTE	is not used */
+/*	PC98BM_SIGNATURE_BYTE	is not used */
+
+#define PC98BM_TIMER_PORT	0xbfdb
+#define PC98BM_DEFAULT_TIMER_VAL	0x00
+
+#define PC98BM_IRQ		13
+
+MODULE_PARM(pc98bm_irq, "i");
+
+static int pc98bm_irq = PC98BM_IRQ;
+static int pc98bm_used = 0;
+
+static void pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static int pc98bm_open(struct input_dev *dev)
+{
+	if (pc98bm_used++)
+		return 0;
+	if (request_irq(pc98bm_irq, pc98bm_interrupt, 0, "98busmouse", NULL)) {
+		pc98bm_used--;
+		printk(KERN_ERR "98busmouse.c: Can't allocate irq %d\n", pc98bm_irq);
+		return -EBUSY;
+	}
+	outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
+	return 0;
+}
+
+static void pc98bm_close(struct input_dev *dev)
+{
+	if (--pc98bm_used)
+		return;
+	outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
+	free_irq(pc98bm_irq, NULL);
+}
+
+static struct input_dev pc98bm_dev = {
+	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
+	.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
+	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
+	.open	= pc98bm_open,
+	.close	= pc98bm_close,
+	.name	= "PC-9801 bus mouse",
+	.phys	= "isa7fd9/input0",
+	.id	= {
+		.bustype = BUS_ISA,
+		.vendor  = 0x0004,
+		.product = 0x0001,
+		.version = 0x0100,
+	},
+};
+
+static void pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	char dx, dy;
+	unsigned char buttons;
+
+	outb(PC98BM_READ_X_LOW, PC98BM_CONTROL_PORT);
+	dx = (inb(PC98BM_DATA_PORT) & 0xf);
+	outb(PC98BM_READ_X_HIGH, PC98BM_CONTROL_PORT);
+	dx |= (inb(PC98BM_DATA_PORT) & 0xf) << 4;
+	outb(PC98BM_READ_Y_LOW, PC98BM_CONTROL_PORT);
+	dy = (inb(PC98BM_DATA_PORT) & 0xf);
+	outb(PC98BM_READ_Y_HIGH, PC98BM_CONTROL_PORT);
+	buttons = inb(PC98BM_DATA_PORT);
+	dy |= (buttons & 0xf) << 4;
+	buttons = ~buttons >> 5;
+
+	input_report_rel(&pc98bm_dev, REL_X, dx);
+	input_report_rel(&pc98bm_dev, REL_Y, dy);
+	input_report_key(&pc98bm_dev, BTN_RIGHT,  buttons & 1);
+	input_report_key(&pc98bm_dev, BTN_MIDDLE, buttons & 2);
+	input_report_key(&pc98bm_dev, BTN_LEFT,   buttons & 4);
+	input_sync(&pc98bm_dev);
+
+	outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
+}
+
+#ifndef MODULE
+static int __init pc98bm_setup(char *str)
+{
+        int ints[4];
+        str = get_options(str, ARRAY_SIZE(ints), ints);
+        if (ints[0] > 0) pc98bm_irq = ints[1];
+        return 1;
+}
+__setup("pc98bm_irq=", pc98bm_setup);
+#endif
+
+static int __init pc98bm_init(void)
+{
+	int i;
+
+	for (i = 0; i <= 6; i += 2) {
+		if (!request_region(PC98BM_BASE + i, 1, "98busmouse")) {
+			printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_BASE + i);
+			while (i > 0) {
+				i -= 2;
+				release_region(PC98BM_BASE + i, 1);
+			}
+
+			return -EBUSY;
+		}
+
+	}
+
+	if (!request_region(PC98BM_TIMER_PORT, 1, "98busmouse")) {
+		printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_TIMER_PORT);
+		for (i = 0; i <= 6; i += 2)
+			release_region(PC98BM_BASE + i, 1);
+
+		return -EBUSY;
+	}
+
+	outb(PC98BM_DEFAULT_MODE, PC98BM_CONFIG_PORT);
+	outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
+
+	outb(PC98BM_DEFAULT_TIMER_VAL, PC98BM_TIMER_PORT);
+
+	input_register_device(&pc98bm_dev);
+	
+	printk(KERN_INFO "input: PC-9801 bus mouse at %#x irq %d\n", PC98BM_BASE, pc98bm_irq);
+
+	return 0;
+}
+
+static void __exit pc98bm_exit(void)
+{
+	int i;
+
+	input_unregister_device(&pc98bm_dev);
+	for (i = 0; i <= 6; i += 2)
+		release_region(PC98BM_BASE + i, 1);
+
+	release_region(PC98BM_TIMER_PORT, 1);
+}
+
+module_init(pc98bm_init);
+module_exit(pc98bm_exit);
diff -urN linux/drivers/input/mouse/Config.in linux98/drivers/input/mouse/Config.in
--- linux/drivers/input/mouse/Config.in	Sat Oct 19 13:02:28 2002
+++ linux98/drivers/input/mouse/Config.in	Thu Oct 24 16:59:32 2002
@@ -22,3 +22,6 @@
 if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
    dep_tristate '  Acorn RiscPC mouse' CONFIG_MOUSE_ACORN $CONFIG_INPUT $CONFIG_INPUT_MOUSE
 fi
+if [ "$CONFIG_PC9800" = "y" ]; then
+   dep_tristate '  NEC PC-9801 busmouse' CONFIG_BUSMOUSE_PC9800 $CONFIG_INPUT $CONFIG_INPUT_MOUSE $CONFIG_ISA
+fi
diff -urN linux/drivers/input/mouse/Makefile linux98/drivers/input/mouse/Makefile
--- linux/drivers/input/mouse/Makefile	Sat Oct 19 13:01:17 2002
+++ linux98/drivers/input/mouse/Makefile	Thu Oct 24 17:00:51 2002
+++ 
@@ -12,6 +12,7 @@
 obj-$(CONFIG_MOUSE_PC110PAD)	+= pc110pad.o
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
+obj-$(CONFIG_BUSMOUSE_PC9800)	+= 98busmouse.o
 
 # The global Rules.make.
 
diff -urN linux/drivers/input/serio/Config.in linux98/drivers/input/serio/Config.in
--- linux/drivers/input/serio/Config.in	Sat Oct 12 13:22:11 2002
+++ linux98/drivers/input/serio/Config.in	Sun Oct 13 12:59:05 2002
@@ -21,3 +21,6 @@
 if [ "$CONFIG_SA1111" = "y" ]; then
    dep_tristate '  Intel SA1111 keyboard controller' CONFIG_SERIO_SA1111 $CONFIG_SERIO
 fi
+if [ "$CONFIG_PC9800" = "y" ]; then
+   dep_tristate '  NEC PC-9801 keyboard controller' CONFIG_SERIO_98KBD $CONFIG_SERIO
+fi
diff -urN linux/drivers/input/serio/Makefile linux98/drivers/input/serio/Makefile
--- linux/drivers/input/serio/Makefile	Sat Oct 19 13:01:09 2002
+++ linux98/drivers/input/serio/Makefile	Thu Oct 24 15:50:55 2002
@@ -17,6 +17,7 @@
 obj-$(CONFIG_SERIO_SA1111)	+= sa1111ps2.o
 obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
+obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
 
 # The global Rules.make.
 
diff -urN linux/drivers/input/serio/98kbd-io.c linux98/drivers/input/serio/98kbd-io.c
--- linux/drivers/input/serio/98kbd-io.c	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/input/serio/98kbd-io.c	Thu Oct 24 16:29:57 2002
@@ -0,0 +1,181 @@
+/*
+ *  NEC PC-9801 keyboard controller driver for Linux
+ *
+ *  Copyright (c) 1999-2002 Osamu Tomita <tomita@cinet.co.jp>
+ *    Based on i8042.c written by Vojtech Pavlik
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <asm/io.h>
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/sched.h>
+
+MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
+MODULE_DESCRIPTION("NEC PC-9801 keyboard controller driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Names.
+ */
+
+#define KBD98_PHYS_DESC "isa0041/serio0"
+
+/*
+ * IRQs.
+ */
+
+#define KBD98_IRQ	1
+
+/*
+ * Register numbers.
+ */
+
+#define KBD98_COMMAND_REG	0x43	
+#define KBD98_STATUS_REG	0x43	
+#define KBD98_DATA_REG		0x41
+
+spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED;
+
+static struct serio kbd98_port;
+extern struct pt_regs *kbd_pt_regs;
+
+static void kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/*
+ * kbd98_flush() flushes all data that may be in the keyboard buffers
+ */
+
+static int kbd98_flush(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd98io_lock, flags);
+
+	while (inb(KBD98_STATUS_REG) & 0x02) /* RxRDY */
+		inb(KBD98_DATA_REG);
+
+	if (inb(KBD98_STATUS_REG) & 0x38)
+		printk("98kbd-io: Keyboard error!\n");
+
+	spin_unlock_irqrestore(&kbd98io_lock, flags);
+
+	return 0;
+}
+
+/*
+ * kbd98_write() sends a byte out through the keyboard interface.
+ */
+
+static int kbd98_write(struct serio *port, unsigned char c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd98io_lock, flags);
+
+	outb(0, 0x5f);			/* wait */
+	outb(0x17, KBD98_COMMAND_REG);	/* enable send command */
+	outb(0, 0x5f);			/* wait */
+	outb(c, KBD98_DATA_REG);
+	outb(0, 0x5f);			/* wait */
+	outb(0x16, KBD98_COMMAND_REG);	/* disable send command */
+	outb(0, 0x5f);			/* wait */
+
+	spin_unlock_irqrestore(&kbd98io_lock, flags);
+
+	return 0;
+}
+
+/*
+ * kbd98_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and enables in in the chip.
+ */
+
+static int kbd98_open(struct serio *port)
+{
+	kbd98_flush();
+
+	if (request_irq(KBD98_IRQ, kbd98io_interrupt, 0, "kbd98", NULL)) {
+		printk(KERN_ERR "98kbd-io.c: Can't get irq %d for %s, unregistering the port.\n", KBD98_IRQ, "KBD");
+		serio_unregister_port(port);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void kbd98_close(struct serio *port)
+{
+	free_irq(KBD98_IRQ, NULL);
+
+	kbd98_flush();
+}
+
+/*
+ * Structures for registering the devices in the serio.c module.
+ */
+
+static struct serio kbd98_port =
+{
+	.type =		SERIO_PC9800,
+	.write =	kbd98_write,
+	.open =		kbd98_open,
+	.close =	kbd98_close,
+	.driver =	NULL,
+	.name =		"PC-9801 Kbd Port",
+	.phys =		KBD98_PHYS_DESC,
+};
+
+/*
+ * kbd98io_interrupt() is the most important function in this driver -
+ * it handles the interrupts from keyboard, and sends incoming bytes
+ * to the upper layers.
+ */
+
+static void kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+	unsigned char data;
+
+#ifdef CONFIG_VT
+	kbd_pt_regs = regs;
+#endif
+
+	spin_lock_irqsave(&kbd98io_lock, flags);
+
+	data = inb(KBD98_DATA_REG);
+	spin_unlock_irqrestore(&kbd98io_lock, flags);
+	serio_interrupt(&kbd98_port, data, 0);
+
+}
+
+int __init kbd98io_init(void)
+{
+	serio_register_port(&kbd98_port);
+
+	printk(KERN_INFO "serio: PC-9801 %s port at %#lx,%#lx irq %d\n",
+	       "KBD",
+	       (unsigned long) KBD98_DATA_REG,
+	       (unsigned long) KBD98_COMMAND_REG,
+	       KBD98_IRQ);
+
+	return 0;
+}
+
+void __exit kbd98io_exit(void)
+{
+	serio_unregister_port(&kbd98_port);
+}
+
+module_init(kbd98io_init);
+module_exit(kbd98io_exit);
diff -urN linux/drivers/char/keyboard.c linux98/drivers/char/keyboard.c
--- linux/drivers/char/keyboard.c	Sat Oct 19 13:01:49 2002
+++ linux98/drivers/char/keyboard.c	Sun Oct 27 09:12:29 2002
@@ -58,7 +58,11 @@
  * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
  * This seems a good reason to start with NumLock off.
  */
+#ifndef CONFIG_PC9800
 #define KBD_DEFLEDS 0
+#else
+#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+#endif
 #endif
 
 #ifndef KBD_DEFLOCK
diff -urN linux/include/linux/kbd_kern.h linux98/include/linux/kbd_kern.h
--- linux/include/linux/kbd_kern.h	Sat Oct 19 13:02:28 2002
+++ linux98/include/linux/kbd_kern.h	Sun Oct 27 10:23:23 2002
@@ -43,11 +43,12 @@
 #define LED_SHOW_IOCTL 1        /* only change leds upon ioctl */
 #define LED_SHOW_MEM 2          /* `heartbeat': peek into memory */
 
-	unsigned char ledflagstate:3;	/* flags, not lights */
-	unsigned char default_ledflagstate:3;
+	unsigned char ledflagstate:4;	/* flags, not lights */
+	unsigned char default_ledflagstate:4;
 #define VC_SCROLLOCK	0	/* scroll-lock mode */
 #define VC_NUMLOCK	1	/* numeric lock mode */
 #define VC_CAPSLOCK	2	/* capslock mode */
+#define VC_KANALOCK	3	/* kanalock mode */
 
 	unsigned char kbdmode:2;	/* one 2-bit value */
 #define VC_XLATE	0	/* translate keycodes using keymap */
diff -urN linux/include/linux/keyboard.h linux98/include/linux/keyboard.h
--- linux/include/linux/keyboard.h	Sat Oct 19 13:01:13 2002
+++ linux98/include/linux/keyboard.h	Mon Oct 21 15:59:48 2002
@@ -9,6 +9,7 @@
 #define KG_ALT		3
 #define KG_ALTGR	1
 #define KG_SHIFTL	4
+#define KG_KANASHIFT	4
 #define KG_SHIFTR	5
 #define KG_CTRLL	6
 #define KG_CTRLR	7

^ permalink raw reply

* RE: ASUS TUSL2-C and Promise Ultra100 TX2
From: Cajoline @ 2002-10-27  2:26 UTC (permalink / raw)
  To: Robbert Kouprie; +Cc: linux-kernel
In-Reply-To: <008b01c27cfd$5a6f7820$020da8c0@nitemare>



On Sat, 26 Oct 2002, Robbert Kouprie wrote:

> > This board should be rather similar to mine, with the main difference
> > being suport for Coppermine/Tualatin processors.
> > also use the PIIX4 onboard IDE chipset?
>
> >From the Asus website, the motherboards are very similar, both have the
> Intel 815 north bridge, and both have the ICH2 (Intel 82801BA Enhanced
> I/O Controller Hub 2) IDE controller onboard. This chip is handled by
> the piix.c driver.

Right, it is ICH2. However, when I boot on Red Hat's 2.4.18 kernels, the
chipset is always reported as PIIX4, not as ICH2, but for example on the
2.4.19 stock kernel I compiled, it is reported as ICH2; yet the two
kernels display the same behavior regarding this issue.
This difference couldn't be a problem though, right?

> > Indeed, that could be a workaround, but I'm afraid it's not that good
> > after all, because not all the drives have the same capabilities, it's
> > still slower than udma 5 (UDMA100) and from my tests, with such a
> > forced setting, the performance is still poor even for this udma mode.
>
> Note that "ata66" actually means UDMA66 and up (it actually means that
> you use 80-conductor cables), so with this parameter your drive _will_
> run at UDMA 100 if that's supported by the drive and controller. I have
> several boxes which need this parameter with the Linus kernel tree, and
> they all have disks running at UDMA100 with this boot parameter. Also,
> my tests show good speeds on these drives.

I'm sorry, I made a mistake; I meant to write I tried the idebus=66 kernel
parameter, not the one you mentioned. The idebus option didn't have any
effect. I will try the ideX=66 one soon.

> > This is interesting. Excuse my ignorance, but do you know what has
> > actually changed exactly regarding PDC20268 and PDC20269?
>
> LBA48 support (for disks > 127Gb) I think was added.

Somehow I believe LBA48 is already supported in 2.4.19 and even 2.4.18. I
have a 160 GB Maxtor drive attached to one of the PDCs (which have already
been flashed with the latest bios that supports LBA48) and it operates
at its' full capacity.

> This night, I experienced another hang on my box. Even magic sysreq
> doesn't do anything anymore. Do you have a reproducible testcase to
> trigger this?

No unfortunately not, that's the whole point here, I don't have any sign
whatsoever of what causes this and where the problem is, since I also
don't get any error or diagnostic whatsoever. Otherwise I would perhaps be
able to narrow it down.
I have noticed this always occurs when reading (copying) from the devices
on the PDCs to another disk. Actually, the disks on the PDCs are all part
in a logical volume (LVM) together with hdc (on the ICH2). I try to copy
files from the LV (ext3 fs) to hdb1 (vfat), and the system always hangs at
some point, which I can not even determine.
I haven't been able to cause the same problem when writing to the LV.
I doubt the LVM code could have something to do with this, but I should
try this with a single partition on a disk attached to the PDC anyway.
Will do very soon.

> > OK fine, I agree, but how do you explain this only happens
> > when running on
> > this motherboard?
>
> Maybe we should start blaming the onboard ICH2 controller, or the piix.c
> driver in this case, because that's the only common thing in our faulty
> setups. I also noticed that the ICH2 on the Asus TUSL2-C and CUSL2-C
> boards have its own PCI device id in the pci.ids file. So this could
> mean they have something different than regular ICH2 chips. I'll include
> my full lspci -vvvx for anyone who is interested.

I will also send the output of lspci soon enough, in case it makes any
sense to your or anyone else. I just can't do it right away.

> > Indeed. The same controllers work just fine on a P3 600 + QDI
> > Advance 10F
> > motherboard (with onboard VIA vt82c686a IDE UDMA66 controller).
>
> Did you also try this motherboard with a different brand add-on PCI
> controller (like a CMD one)?

No, I don't have any other brand cards to use. I remember I also tried one
Ultra66 controller on this board and it worked fine.

Thanks for your help and comments - they have been quite helpful.
I will try the current -ac tree patches, as well as everything noted
above, and write back asap with my findings.

Regards,
CJ Leblanc


^ permalink raw reply

* bkbits cleanups
From: Larry McVoy @ 2002-10-27  2:31 UTC (permalink / raw)
  To: linux-kernel

Hi, 

I was cleaning up the empty projects listed below and I think I may
have removed one which wasn't empty by mistake, the linuxquestions repo.
If so, my apologies.

We go through the repos periodically and remove the ones which look like they
were setup mistakes (idle and no content).

Going forward, we need to modify the setup system on bkbits to get an email
address for the owner so we can send them mail in case it looks like their
project is idle and no longer needed.

--lm

fbar1
fmarostica
fmarostica1
foobar
jhcfonts
libtomcrypt
linux-misc
linux-mm
linuxquestions
obelisk
programdev
teste2
zlinux


^ permalink raw reply

* Re: [parisc-linux] SQUID failled :(
From: Grant Grundler @ 2002-10-27  2:00 UTC (permalink / raw)
  To: Joel Soete; +Cc: parisc-linux
In-Reply-To: <3DBAD5D4.8020900@freebel.net>

Joel Soete wrote:
> Is somebody reach to make squid running on a woody pa-box?
> I install it (to replace a old pentium 100Mhz box).
> Well it start some second(s) then stop without any message anywhere 

you check dmesg output?

grant

^ permalink raw reply

* [PATCH]  2.5.44 update axnet_cs.c to support AX88790 chipset
From: Henry Andersen @ 2002-10-27  2:02 UTC (permalink / raw)
  To: linux-kernel


Hi,

I update the axnet_cs.c to support Asix AX88790 chipset.
This code comes from the stand-alone pcmcia-cs axnet_cs.c ver1.26.

>eth0: Asix AX88790: io 0x300, irq 5, hw_addr 00:40:26:xx:xx:xx
>eth0: found link beat
>eth0: autonegotiation complete: 100baseT-FD selected



--- drivers/net/pcmcia/axnet_cs.c.orig	Sat Oct 19 13:01:57 2002
+++ drivers/net/pcmcia/axnet_cs.c	Sat Oct 26 21:22:16 2002
@@ -11,7 +11,7 @@
 
     Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
 
-    axnet_cs.c 1.11 2001/06/12 12:42:40
+    axnet_cs.c 1.26 2002/02/17 23:30:21
     
     The network driver code is based on Donald Becker's NE2000 code:
 
@@ -20,7 +20,7 @@
     Director, National Security Agency.  This software may be used and
     distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
-    Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
+    Donald Becker may be reached at becker@scyld.com
 
 ======================================================================*/
 
@@ -33,14 +33,13 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <asm/uaccess.h>
+#include <linux/spinlock.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <linux/netdevice.h>
-#include "ax8390.h"
+#include "../8390.h"
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -53,34 +52,25 @@
 #define AXNET_CMD	0x00
 #define AXNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */
 #define AXNET_RESET	0x1f	/* Issue a read to reset, a write to clear. */
-#define AXNET_MISC	0x18	/* For IBM CCAE and Socket EA cards */
 #define AXNET_MII_EEP	0x14	/* Offset of MII access port */
+#define AXNET_TEST	0x15	/* Offset of TEST Register port */
+#define AXNET_GPIO	0x17	/* Offset of General Purpose Register Port */
 
 #define AXNET_START_PG	0x40	/* First page of TX buffer */
 #define AXNET_STOP_PG	0x80	/* Last page +1 of RX ring */
 
 #define AXNET_RDC_TIMEOUT 0x02	/* Max wait in jiffies for Tx RDC */
 
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"axnet_cs.c 1.11 2001/06/12 12:42:40 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
-#define skb_tx_check(dev, skb)
-#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
-#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
-#define netif_mark_up(dev)	do { } while (0)
-#define netif_mark_down(dev)	do { } while (0)
+#define IS_AX88190	0x0001
+#define IS_AX88790	0x0002
 
 /*====================================================================*/
 
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
 
 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
 
@@ -89,9 +79,14 @@
 static int irq_list[4] = { -1 };
 MODULE_PARM(irq_list, "1-4i");
 
-/* Ugh!  Let the user hardwire the hardware address for queer cards */
-static int hw_addr[6] = { 0, /* ... */ };
-MODULE_PARM(hw_addr, "6i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"axnet_cs.c 1.26 2002/02/17 23:30:21 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
 
 /*====================================================================*/
 
@@ -122,6 +117,12 @@
 static dev_info_t dev_info = "axnet_cs";
 static dev_link_t *dev_list;
 
+static int axdev_init(struct net_device *dev);
+static void AX88190_init(struct net_device *dev, int startp);
+static int ax_open(struct net_device *dev);
+static int ax_close(struct net_device *dev);
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
 /*====================================================================*/
 
 typedef struct axnet_dev_t {
@@ -134,6 +135,7 @@
     u_short		link_status;
     u_char		duplex_flag;
     int			phy_id;
+    int			flags;
 } axnet_dev_t;
 
 /*======================================================================
@@ -212,7 +214,7 @@
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    ethdev_init(dev);
+    axdev_init(dev);
     dev->init = &axnet_init;
     dev->open = &axnet_open;
     dev->stop = &axnet_close;
@@ -304,7 +306,7 @@
 	{0x00,	EN0_RCNTHI},
 	{0x00,	EN0_IMR},	/* Mask completion irq. */
 	{0xFF,	EN0_ISR},
-	{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+	{E8390_RXOFF|0x40, EN0_RXCR},	/* 0x60  Set to monitor */
 	{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
 	{0x10,	EN0_RCNTLO},
 	{0x00,	EN0_RCNTHI},
@@ -333,30 +335,6 @@
 
 /*======================================================================
 
-    This should be totally unnecessary... but when we can't figure
-    out the hardware address any other way, we'll let the user hard
-    wire it when the module is initialized.
-
-======================================================================*/
-
-static int get_hwired(dev_link_t *link)
-{
-    struct net_device *dev = link->priv;
-    int i;
-
-    for (i = 0; i < 6; i++)
-	if (hw_addr[i] != 0) break;
-    if (i == 6)
-	return 0;
-
-    for (i = 0; i < 6; i++)
-	dev->dev_addr[i] = hw_addr[i];
-
-    return 1;
-} /* get_hwired */
-
-/*======================================================================
-
     axnet_config() is scheduled to run after a CARD_INSERTION event
     is received, to configure the PCMCIA socket, and to make the
     ethernet device available to the system.
@@ -421,7 +399,8 @@
     CS_CHECK(GetTupleData, handle, &tuple);
     CS_CHECK(ParseTuple, handle, &tuple, &parse);
     link->conf.ConfigBase = parse.config.base;
-    link->conf.Present = parse.config.rmask[0];
+    /* don't trust the CIS on this; Linksys got it wrong */
+    link->conf.Present = 0x63;
 
     /* Configure card */
     link->state |= DEV_CONFIG;
@@ -442,7 +421,7 @@
 	if ((cfg->index == 0) || (cfg->io.nwin == 0))
 	    goto next_entry;
 	
-	link->conf.ConfigIndex = cfg->index;
+	link->conf.ConfigIndex = 0x05;
 	/* For multifunction cards, by convention, we configure the
 	   network function with window 0, and serial with window 1 */
 	if (io->nwin > 1) {
@@ -482,9 +461,9 @@
 	goto failed;
     }
 
-    if (!get_prom(link) && !get_hwired(link)) {
-	printk(KERN_NOTICE "axnet_cs: unable to read hardware net"
-	       " address for io base %#3lx\n", dev->base_addr);
+    if (!get_prom(link)) {
+	printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
+	printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
 	unregister_netdev(dev);
 	goto failed;
     }
@@ -503,15 +482,37 @@
     link->dev = &info->node;
     link->state &= ~DEV_CONFIG_PENDING;
 
-    printk(KERN_INFO "%s: Asix AX88190: io %#3lx, irq %d, hw_addr ",
-	   dev->name, dev->base_addr, dev->irq);
+    if (inb(dev->base_addr + AXNET_TEST) != 0)
+	info->flags |= IS_AX88790;
+    else
+	info->flags |= IS_AX88190;
+
+    printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
+		dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
+		dev->base_addr, dev->irq);
     for (i = 0; i < 6; i++)
 	printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
 
+    if (info->flags & IS_AX88790)
+	outb(0x10, dev->base_addr + AXNET_GPIO);  /* select Internal PHY */
+
     for (i = 0; i < 32; i++) {
 	j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
 	if ((j != 0) && (j != 0xffff)) break;
     }
+
+
+    /* Maybe PHY is in power down mode. (PPD_SET = 1) 
+       Bit 2 of CCSR is active low. */ 
+    if (i == 32) {
+	conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
+ 	CardServices(AccessConfigurationRegister, link->handle, &reg);
+	for (i = 0; i < 32; i++) {
+	    j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+	    if ((j != 0) && (j != 0xffff)) break;
+	}
+    }
+
     info->phy_id = (i < 32) ? i : -1;
     if (i < 32) {
 	DEBUG(0, "  MII transceiver at index %d, status %x.\n", i, j);
@@ -544,7 +545,7 @@
 
     if (link->open) {
 	DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
-	      info->node.dev_name);
+	      ((axnet_dev_t *)(link->priv))->node.dev_name);
 	link->state |= DEV_STALE_CONFIG;
 	return;
     }
@@ -604,7 +605,7 @@
 	    CardServices(RequestConfiguration, link->handle, &link->conf);
 	    if (link->open) {
 		axnet_reset_8390(&info->dev);
-		NS8390_init(&info->dev, 1);
+		AX88190_init(&info->dev, 1);
 		netif_device_attach(&info->dev);
 	    }
 	}
@@ -694,7 +695,7 @@
     info->watchdog.expires = jiffies + HZ;
     add_timer(&info->watchdog);
 
-    return ei_open(dev);
+    return ax_open(dev);
 } /* axnet_open */
 
 /*====================================================================*/
@@ -706,11 +707,11 @@
 
     DEBUG(2, "axnet_close('%s')\n", dev->name);
 
+    ax_close(dev);
     free_irq(dev->irq, dev);
     
     link->open--;
     netif_stop_queue(dev);
-    netif_mark_down(dev);
     del_timer(&info->watchdog);
     if (link->state & DEV_STALE_CONFIG)
 	mod_timer(&link->release, jiffies + HZ/20);
@@ -757,7 +758,7 @@
 {
     axnet_dev_t *info = dev_id;
     info->stale = 0;
-    ei_interrupt(irq, dev_id, regs);
+    ax_interrupt(irq, dev_id, regs);
 }
 
 static void ei_watchdog(u_long arg)
@@ -809,7 +810,7 @@
 	    else
 		printk(KERN_INFO "%s: link partner did not autonegotiate\n",
 		       dev->name);
-	    NS8390_init(dev, 1);
+	    AX88190_init(dev, 1);
 	}
 	info->link_status = link;
     }
@@ -819,27 +820,6 @@
     add_timer(&info->watchdog);
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
-{
-    u32 ethcmd;
-
-    if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-	return -EFAULT;
-
-    switch (ethcmd) {
-    case ETHTOOL_GDRVINFO: {
-	struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-
-	strncpy(info.driver, "axnet_cs", sizeof(info.driver)-1);
-	if (copy_to_user(useraddr, &info, sizeof(info)))
-	    return -EFAULT;
-	return 0;
-    }
-    }
-
-    return -EOPNOTSUPP;
-}
-
 /*====================================================================*/
 
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -848,8 +828,6 @@
     u16 *data = (u16 *)&rq->ifr_data;
     ioaddr_t mii_addr = dev->base_addr + AXNET_MII_EEP;
     switch (cmd) {
-    case SIOCETHTOOL:
-	return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
     case SIOCDEVPRIVATE:
 	data[0] = info->phy_id;
     case SIOCDEVPRIVATE+1:
@@ -940,7 +918,7 @@
     if (serv.Revision != CS_RELEASE_CODE) {
 	printk(KERN_NOTICE "axnet_cs: Card Services release "
 	       "does not match!\n");
-	return -1;
+	return -EINVAL;
     }
     register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach);
     return 0;
@@ -969,10 +947,11 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-  
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
   This is the chip-specific code for many 8390-based ethernet adaptors.
   This is not a complete driver, it must be combined with board-specific
   code such as ne.c, wd.c, 3c503.c, etc.
@@ -982,7 +961,6 @@
   a simple innocent change. Please contact me or Donald if you think
   you have found something that needs changing. -- PG
 
-
   Changelog:
 
   Paul Gortmaker	: remove set_bit lock, other cleanups.
@@ -1006,8 +984,8 @@
 
   */
 
-static const char *version =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+static const char *version_8390 =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -1087,25 +1065,23 @@
  *	them.
  */
  
-
-\f
 /**
- * ei_open - Open/initialize the board.
+ * ax_open - Open/initialize the board.
  * @dev: network device to initialize
  *
  * This routine goes all-out, setting everything
  * up anew at each open, even though many of these registers should only
  * need to be set once at boot.
  */
-static int ei_open(struct net_device *dev)
+static int ax_open(struct net_device *dev)
 {
 	unsigned long flags;
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 
-	/* This can't happen unless somebody forgot to call ethdev_init(). */
+	/* This can't happen unless somebody forgot to call axdev_init(). */
 	if (ei_local == NULL) 
 	{
-		printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
+		printk(KERN_EMERG "%s: ax_open passed a non-existent device!\n", dev->name);
 		return -ENXIO;
 	}
 
@@ -1124,35 +1100,36 @@
 	 */
       
       	spin_lock_irqsave(&ei_local->page_lock, flags);
-	NS8390_init(dev, 1);
+	AX88190_init(dev, 1);
 	/* Set the flag before we drop the lock, That way the IRQ arrives
 	   after its set and we get no silly warnings */
-	netif_mark_up(dev);
 	netif_start_queue(dev);
       	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	ei_local->irqlock = 0;
 	return 0;
 }
 
+#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
+
 /**
- * ei_close - shut down network device
+ * ax_close - shut down network device
  * @dev: network device to close
  *
- * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
+ * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
  */
-static int ei_close(struct net_device *dev)
+int ax_close(struct net_device *dev)
 {
-	unsigned long flags;
+        unsigned long flags;
 
-	/*
-	 *	Hold the page lock during close
-	 */
-
-	spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
-	NS8390_init(dev, 0);
-	spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
-	netif_stop_queue(dev);
-	return 0;
+        /*
+         *      Hold the page lock during close
+         */
+
+	spin_lock_irqsave(&dev_lock(dev), flags);
+        AX88190_init(dev, 0);
+	spin_unlock_irqrestore(&dev_lock(dev), flags);
+        netif_stop_queue(dev);
+        return 0;
 }
 
 /**
@@ -1194,7 +1171,7 @@
 		
 	/* Try to restart the card.  Perhaps the user has fixed something. */
 	ei_reset_8390(dev);
-	NS8390_init(dev, 1);
+	AX88190_init(dev, 1);
 		
 	spin_unlock(&ei_local->page_lock);
 	enable_irq(dev->irq);
@@ -1217,7 +1194,6 @@
 	unsigned long flags;
 
 	netif_stop_queue(dev);
-	skb_tx_check(dev, skb);
 
 	length = skb->len;
 
@@ -1230,7 +1206,6 @@
 	outb_p(0x00, e8390_base + EN0_IMR);
 	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	
-	
 	/*
 	 *	Slow phase with lock held.
 	 */
@@ -1243,8 +1218,6 @@
 
 	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
     
-#ifdef EI_PINGPONG
-
 	/*
 	 * We have two Tx slots available for use. Find the first free
 	 * slot, and then perform some sanity checks. With two Tx bufs,
@@ -1313,22 +1286,6 @@
 	else
 		netif_start_queue(dev);
 
-#else	/* EI_PINGPONG */
-
-	/*
-	 * Only one Tx buffer in use. You need two Tx bufs to come close to
-	 * back-to-back transmits. Expect a 20 -> 25% performance hit on
-	 * reasonable hardware if you only use one Tx buffer.
-	 */
-
-	ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
-	ei_local->txing = 1;
-	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
-	dev->trans_start = jiffies;
-	netif_stop_queue(dev);
-
-#endif	/* EI_PINGPONG */
-
 	/* Turn 8390 interrupts back on. */
 	ei_local->irqlock = 0;
 	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1336,14 +1293,14 @@
 	spin_unlock(&ei_local->page_lock);
 	enable_irq(dev->irq);
 
-	DEV_KFREE_SKB (skb);
-	add_tx_bytes(&ei_local->stat, send_length);
+	dev_kfree_skb (skb);
+	ei_local->stat.tx_bytes += send_length;
     
 	return 0;
 }
 \f
 /**
- * ei_interrupt - handle the interrupts from an 8390
+ * ax_interrupt - handle the interrupts from an 8390
  * @irq: interrupt number
  * @dev_id: a pointer to the net_device
  * @regs: unused
@@ -1355,7 +1312,7 @@
  * needed.
  */
 
-static void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	long e8390_base;
@@ -1522,8 +1479,6 @@
 	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 	int status = inb(e8390_base + EN0_TSR);
     
-#ifdef EI_PINGPONG
-
 	/*
 	 * There are two Tx buffers, see which one finished, and trigger
 	 * the send of another one if it exists.
@@ -1566,13 +1521,6 @@
 //	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
 //			dev->name, ei_local->lasttx);
 
-#else	/* EI_PINGPONG */
-	/*
-	 *  Single Tx buffer: mark it free so another packet can be loaded.
-	 */
-	ei_local->txing = 0;
-#endif
-
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
 	if (status & ENTSR_COL)
 		ei_local->stat.collisions++;
@@ -1680,7 +1628,7 @@
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 				ei_local->stat.rx_packets++;
-				add_rx_bytes(&ei_local->stat, pkt_len);
+				ei_local->stat.rx_bytes += pkt_len;
 				if (pkt_stat & ENRSR_PHY)
 					ei_local->stat.multicast++;
 			}
@@ -1826,11 +1774,11 @@
 	long e8390_base = dev->base_addr;
 
   	if(dev->flags&IFF_PROMISC)
-  		outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+  		outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
 	else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
-  		outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+  		outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
   	else
-  		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+  		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
 }
 
 /*
@@ -1838,28 +1786,28 @@
  *	be parallel to just about everything else. Its also fairly quick and
  *	not called too often. Must protect against both bh and irq users
  */
- 
+
 static void set_multicast_list(struct net_device *dev)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
+	spin_lock_irqsave(&dev_lock(dev), flags);
 	do_set_multicast_list(dev);
-	spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
+	spin_unlock_irqrestore(&dev_lock(dev), flags);
 }	
 
 /**
- * ethdev_init - init rest of 8390 device struct
+ * axdev_init - init rest of 8390 device struct
  * @dev: network device structure to init
  *
  * Initialize the rest of the 8390 device structure.  Do NOT __init
  * this, as it is used by 8390 based modular drivers too.
  */
 
-static int ethdev_init(struct net_device *dev)
+static int axdev_init(struct net_device *dev)
 {
 	if (ei_debug > 1)
-		printk(version);
+		printk(version_8390);
     
 	if (dev->priv == NULL) 
 	{
@@ -1882,20 +1830,18 @@
 	return 0;
 }
 \f
-
-
 /* This page of functions should be 8390 generic */
 /* Follow National Semi's recommendations for initializing the "NIC". */
 
 /**
- * NS8390_init - initialize 8390 hardware
+ * AX88190_init - initialize 8390 hardware
  * @dev: network device to initialize
  * @startp: boolean.  non-zero value to initiate chip processing
  *
  *	Must be called with lock held.
  */
 
-static void NS8390_init(struct net_device *dev, int startp)
+static void AX88190_init(struct net_device *dev, int startp)
 {
 	axnet_dev_t *info = (axnet_dev_t *)dev;
 	long e8390_base = dev->base_addr;
@@ -1912,7 +1858,7 @@
 	outb_p(0x00,  e8390_base + EN0_RCNTLO);
 	outb_p(0x00,  e8390_base + EN0_RCNTHI);
 	/* Set to monitor and loopback mode -- this is vital!. */
-	outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+	outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
 	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
 	/* Set the transmit page and receive ring. */
 	outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
@@ -1956,7 +1902,7 @@
 		outb_p(E8390_TXCONFIG | info->duplex_flag,
 		       e8390_base + EN0_TXCR); /* xmit on. */
 		/* 3c503 TechMan says rxconfig only after the NIC is started. */
-		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on,  */
+		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
 		do_set_multicast_list(dev);	/* (re)load the mcast table */
 	}
 }

^ permalink raw reply

* Re: Creating a Hybrid Connection to Balance Traffic
From: Kevin Dwyer @ 2002-10-27  1:28 UTC (permalink / raw)
  To: netfilter
In-Reply-To: <39397.192.168.7.14.1035674081.squirrel@iw.k1k2.com>

On Sun, 27 Oct 2002 10:14:41 +1100 (EST)
Andrew Smith <nfml@k1k2.com> wrote:

> Use google to look up egress, but basically it means that they
> may only allow the source IP of outgoing packets to match the
> IP address they supply you and they drop all other packets.
> This is apparently common in the USA.

But distressingly not common enough.

I know for a fact that Verizon does do this with their DSL which uses
PPPoE (except I was hypothetically testing some theoretical spoofing
ideas ;). I know for a fact dozens of ISPs who do not because it would
load their equipment to excess.

-- 
/* Kevin Dwyer                                Allegiance Internet */
/* network security engineer                   Commerce Center II */
/* email: Kevin.Dwyer@algx.net                7601 Ora Glen Drive */
/* phone: 240-616-2075                        Greenbelt, MD 20770 */
/*      >++++++++++[<++++++++++>-]<.+++++.----.[-]++++++++++.     */



^ permalink raw reply

* Re: [parisc-linux] Branch Prediction
From: Grant Grundler @ 2002-10-27  1:23 UTC (permalink / raw)
  To: John David Anglin; +Cc: parisc-linux
In-Reply-To: <200210261705.g9QH54Zx002355@hiauly1.hia.nrc.ca>

"John David Anglin" wrote:
> I wonder if the PA-8700 in the rp2470 has it?

gsyprf11 is a 650Mhz PA8700. please try it.

> I suppose it also could be an add-on chip.

Think so?
After reading the description I had the impression BTS has to be on chip
and integrated in order to get the speed. But I'm just a SW engineer...

> I am guessing but I think setting it would help on machines with
> dynamic prediction hardware.  There is probably a paper somewhere
> on this on the HP site.

> My understanding is that pc-relative branches can be predicted
> from examination of the code.  Indirect branches (e.g., call
> returns) can't.

yes.  IIRC, branches forward tend to not be taken and branches backwards
tend to be loops. Or something along that line. But with PBO, the
static hints are better. And HPUX has a very cool "driver" called
"flipper" that will flip to static hints to match performance path
at run time.
 
> I don't know how the dynamic prediction hardware
> works but I would think it wouldn't be there if it didn't
> improve branch prediction.

yeah - I'll what I can learn about it this week.

thanks,
grant

^ permalink raw reply

* Re: Sharing the home directory...
From: Jorge R . Csapo @ 2002-10-27  1:20 UTC (permalink / raw)
  To: Ibrahim El-Shafei; +Cc: linux-admin, linux-config
In-Reply-To: <000301c27cf8$32d775b0$2720873e@IBRAHIM>

How didn't it work? Any error messages? Please give us more information.

assim falou Ibrahim El-Shafei (em 26/10/2002):
> Dear Sir,
> I have about 5 linux boxes on my site. I want to make all of them share
> the same home directory and users, so I exported the home directory of
> one of them and then pointed to this home directory as /home for the
> other boxes. It didn't work, why?
> 
> Thank you for your help.
> 
> Yours,
> Ibrahim El-Shafei
> "HimaTech"
> 
> Ibrahim El-Shafei
> "HimaTech"
> -
> To unsubscribe from this list: send the line "unsubscribe linux-admin" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Jorge R. Csapo

--------------------------------------------------
    /"\
    \ /ÿ CAMPANHA DA FITA ASCII - CONTRA MAIL HTML
     Xÿÿ ASCII RIBBON CAMPAIGN - AGAINST HTML MAIL
    / \
--------------------------------------------------
Jorge R. Csapo
http://www.completo.com.br/~jorge
===========================================
With a PC, I always felt limited
by the software available.
On Unix, I am limited only by my knowledge. 
--Peter J. Schoenster
-
To unsubscribe from this list: send the line "unsubscribe linux-config" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Linux 2.5.44-ac4
From: Dieter Nützel @ 2002-10-27  1:20 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linux Kernel List

IDE as modules: Unresolved symbols

make -f arch/i386/lib/Makefile modules_install
if [ -r System.map ]; then /sbin/depmod -ae -F System.map  2.5.44-ac4; fi
depmod: *** Unresolved symbols in 
/lib/modules/2.5.44-ac4/kernel/drivers/ide/ide-disk.o
depmod:         proc_ide_read_geometry
depmod: *** Unresolved symbols in 
/lib/modules/2.5.44-ac4/kernel/drivers/ide/ide-probe.o
depmod:         do_ide_request
depmod:         ide_add_generic_settings
depmod:         ide_bus_type
depmod:         create_proc_ide_interfaces
depmod: *** Unresolved symbols in 
/lib/modules/2.5.44-ac4/kernel/drivers/ide/ide.o
depmod:         ide_release_dma
depmod:         ide_add_proc_entries
depmod:         ide_scan_pcibus
depmod:         proc_ide_read_capacity
depmod:         proc_ide_create
depmod:         ide_remove_proc_entries
depmod:         destroy_proc_ide_drives
depmod:         proc_ide_destroy
depmod:         create_proc_ide_interfaces
depmod: *** Unresolved symbols in 
/lib/modules/2.5.44-ac4/kernel/drivers/ide/pci/amd74xx.o
depmod:         ide_setup_dma_Rsmp_35fed897
depmod:         ide_pci_unregister_driver_Rsmp_dba95e77
depmod:         ide_pci_register_driver_Rsmp_018476ee
depmod:         ide_pci_register_host_proc
depmod:         ide_setup_pci_device_Rsmp_c4237914


CONFIG_AIC7XXX_BUILD_FIRMWARE=y

Not fixed:

This one works:

--- drivers/scsi/aic7xxx/Makefile.Alan  Sun Oct 27 02:20:06 2002
+++ drivers/scsi/aic7xxx/Makefile       Sat Oct 26 03:53:07 2002
@@ -37,12 +37,11 @@ $(addprefix $(obj)/,$(aic7xxx-objs)): $(

 ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)

-$(obj)/aic7xxx_seq.h: $(src)/aic7xxx.seq $(src)/aic7xxx.reg \
-                     $(obj)/aicasm/aicasm
-       $(obj)/aicasm/aicasm -I$(obj) -r $(obj)/aic7xxx_reg.h \
-                                -o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq
-
-$(obj)/aic7xxx_reg.h: $(obj)/aix7xxx_seq.h
+$(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h: $(src)/aic7xxx.seq \
+                                           $(src)/aic7xxx.reg \
+                                           $(obj)/aicasm/aicasm
+       $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
+                                 -o $(obj)/aic7xxx_seq.h $(src)/aic7xxx.seq

 $(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl]
        $(MAKE) -C $(src)/aicasm

Regards,
	Dieter

^ permalink raw reply

* (no subject)
From: Paul Komarek @ 2002-10-27  1:16 UTC (permalink / raw)
  To: linux-kernel; +Cc: komarek


On Sat Jul 27 2002 - 22:00:06 EST,  mdoelle@linux-user.de wrote:
> this patch for Kernel 2.4.19-rc3 removes the "break" that aborted the
> module init of i810_audio.o in case of "not ready" status before probing
> (line 2656-2663).  On my Epox 4G4A+ mainboard with i845G chipset the

Mirko's patch was sufficient to make sound work on a Dell 4550.

00:1f.5 Multimedia audio controller: Intel Corp. 82801DB AC'97 Audio (rev
01)
	Subsystem: Dell Computer Corporation: Unknown device 0142
	Flags: bus master, medium devsel, latency 0, IRQ 11
	I/O ports at d800 [size=256]
	I/O ports at dc40 [size=64]
	Memory at fe300400 (32-bit, non-prefetchable) [size=512]
	Memory at fe300000 (32-bit, non-prefetchable) [size=256]
	Capabilities: [50] Power Management version 2

Before commenting out the "break" line, the syslogs were filling with
these messages:

------------------------------------------------------------------
Oct 25 20:48:34 liuting kernel: Intel 810 + AC97 Audio, version 0.22,
                                13:45:06 Sep  4 2002
Oct 25 20:48:34 liuting kernel: PCI: Found IRQ 11 for device 00:1f.5
Oct 25 20:48:34 liuting kernel: PCI: Sharing IRQ 11 with 00:1f.3
Oct 25 20:48:34 liuting kernel: PCI: Setting latency timer of device
                                00:1f.5 to 64
Oct 25 20:48:34 liuting kernel: i810: Intel ICH4 found at IO 0xdc40 and
                                0xd800, IRQ 11
Oct 25 20:48:35 liuting insmod:
               /lib/modules/2.4.18-14/kernel/drivers/sound/i810_audio.o:
               init_module: No such device
Oct 25 20:48:35 liuting insmod: Hint: insmod errors can be caused by
      incorrect module parameters, including invalid IO or IRQ parameters.
      You may find more information in syslog or the output from dmesg
Oct 25 20:48:35 liuting insmod:
         /lib/modules/2.4.18-14/kernel/drivers/sound/i810_audio.o: insmod
         sound-slot-0 failed
Oct 25 20:48:35 liuting kernel: i810_audio: Codec not ready.. wait.. no
                                response.
Oct 25 20:48:35 liuting kernel: i810_audio: Audio Controller supports 6
                                channels.
Oct 25 20:48:35 liuting kernel: i810_audio: Defaulting to base 2 channel
                                mode.
Oct 25 20:48:35 liuting kernel: i810_audio: Primary codec not ready.
Oct 25 20:48:35 liuting modprobe: modprobe: Can't locate module
sound-service-0-3
Oct 25 20:48:35 liuting firstboot: sox: Can't open output file '/dev/dsp':
No such device
------------------------------------------------------------------

-Paul Komarek


^ permalink raw reply

* [patch] Problem with mousedev.c
From: Zephaniah E. Hull @ 2002-10-27  1:05 UTC (permalink / raw)
  To: vojtech; +Cc: linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 1016 bytes --]

To make a long story short, mousedev.c does not properly implement the
EXPS/2 protocol, specificly dealing with the wheel.

The lower 8 bits of the 4th byte are supposed to be 0x1 or 0xf to
indicate movement of the first wheel, and 0x2 or 0xe for the second
wheel.

Attached is a patch to correct this.

This does not get my two wheel mouse working perfectly yet, sadly that
will take a bit of a hack, and I'm not sure where the best place to put
it is yet, but this gets it back to generating correct data.

Zephaniah E. Hull.
(Debian GPM maintainer.)

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

  Yes, Java is so bulletproofed that to a C programmer it feels like
being in a straightjacket, but it's a really comfy and warm
straightjacket, and the world would be a safer place if everyone was
straightjacketed most of the time.        -- Overheard in the SDM.

[-- Attachment #1.2: hid.diff --]
[-- Type: text/plain, Size: 1799 bytes --]

diff -ur linux/drivers/input/mousedev.c linux.mine/drivers/input/mousedev.c
--- linux/drivers/input/mousedev.c	2001-09-30 15:26:05.000000000 -0400
+++ linux.mine/drivers/input/mousedev.c	2002-10-26 18:20:19.000000000 -0400
@@ -62,7 +62,7 @@
 	struct fasync_struct *fasync;
 	struct mousedev *mousedev;
 	struct mousedev_list *next;
-	int dx, dy, dz, oldx, oldy;
+	int dw, dx, dy, dz, oldx, oldy;
 	signed char ps2[6];
 	unsigned long buttons;
 	unsigned char ready, buffer, bufsiz;
@@ -117,6 +117,7 @@
 						case REL_X:	list->dx += value; break;
 						case REL_Y:	list->dy -= value; break;
 						case REL_WHEEL:	if (list->mode) list->dz -= value; break;
+						case REL_HWHEEL: if (list->mode == 2) list->dw -= value; break;
 					}
 					break;
 
@@ -260,9 +261,22 @@
 	list->bufsiz = off + 3;
 
 	if (list->mode == 2) {
-		list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz));
-		list->dz -= list->ps2[off + 3];
-		list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1);
+		if (!list->dz && !list->dw) {
+			list->ps2[off + 3] = 0;
+		} else if (list->dw > 0) {
+			list->ps2[off + 3] = 0x2;
+			list->dw--;
+		} else if (list->dw < 0) {
+			list->ps2[off + 3] = 0xe;
+			list->dw++;
+		} else if (list->dz > 0) {
+			list->ps2[off + 3] = 0x1;
+			list->dz--;
+		} else if (list->dz < 0) {
+			list->ps2[off + 3] = 0xf;
+			list->dz++;
+		}
+		list->ps2[off + 3] |= (list->buttons & 0x18) << 1;
 		list->bufsiz++;
 	}
 	
@@ -272,7 +286,7 @@
 		list->bufsiz++;
 	}
 
-	if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0;
+	if (!list->dx && !list->dy && (!list->mode || !list->dz) && ((list->mode != 2) || !list->dw)) list->ready = 0;
 	list->buffer = list->bufsiz;
 }
 

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] ide.c initialisation order
From: Peter Denison @ 2002-10-27  0:58 UTC (permalink / raw)
  To: Alan Cox, Andre Hedrick; +Cc: linux-kernel

Summary: Move ide_init_default_hwifs to ide_init() from ide_init_data()

On non-PCI boxes, in ide_init_data called from very early ide_setup, the
ide_init_default_hwifs() function calls -> ide_register_hw ->
ide_probe_module -> ide_probe_init -> etc. well before loads of other
important things like command-line processing were done. Move it to
ide_init().

(I guess nobody is testing 2.5.xx IDE on non-PCI hardware!)

Whether this call should be there at all is a matter for debate. The whole
of IDE startup is an unholy mess, not least in the plethora of "init",
"register" and "probe" named functions, which are not consistent. However,
now is not the time to tackle that!

Applies: 2.5.44 (and probably others!)

--- drivers/ide/ide.c.old	2002-10-19 12:43:39.000000000 +0100
+++ drivers/ide/ide.c	2002-10-19 23:30:43.000000000 +0100
@@ -345,9 +347,6 @@
 	for (index = 0; index < MAX_HWIFS; ++index)
 		init_hwif_data(index);

-	/* Add default hw interfaces */
-	ide_init_default_hwifs();
-
 	idebus_parameter = 0;
 	system_bus_speed = 0;
 }
@@ -3444,6 +3443,9 @@

 	init_ide_data();

+	/* Add default hw interfaces */
+	ide_init_default_hwifs();
+
 	initializing = 1;
 	ide_init_builtin_drivers();
 	initializing = 0;

-- 
Peter Denison <peterd at marshadder dot uklinux dot net>
Please use the address above only for personal mail, not copied to any lists
that are gatewayed to news or web pages unless the addresses are removed.


^ permalink raw reply

* Re: possible use-after-free in 2.5.44 scsi changes
From: James Bottomley @ 2002-10-27  0:50 UTC (permalink / raw)
  To: Jens Axboe
  Cc: James Bottomley, Badari Pulavarty, Andrew Morton,
	linux-scsi@vger.kernel.org, Martin J. Bligh, Doug Ledford
In-Reply-To: <20021026092943.GB14976@suse.de>

[-- Attachment #1: Type: text/plain, Size: 315 bytes --]

axboe@suse.de said:
> Irk no, you cannot just clear valid information! This is _not_ a fix,
> it's a hack.

> Use a different flag, or maybe use REQ_DONTPREP or similar. 

OK, what about this.  It uses REQ_DONTPREP, and could be a precursor to moving 
the SCSI subsystem to using the request prep function.

James


[-- Attachment #2: tmp.diff --]
[-- Type: text/plain , Size: 2773 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.823   -> 1.824  
#	 drivers/scsi/scsi.h	1.30    -> 1.31   
#	drivers/scsi/scsi_lib.c	1.36    -> 1.37   
#	 drivers/scsi/scsi.c	1.50    -> 1.51   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/26	jejb@mulgrave.(none)	1.824
# [SCSI] fix memory etc. leak caused by double preparing requeued commands
# --------------------------------------------
#
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Sat Oct 26 19:46:01 2002
+++ b/drivers/scsi/scsi.c	Sat Oct 26 19:46:01 2002
@@ -658,7 +658,7 @@
  * Notes:       This could be called either from an interrupt context or a
  *              normal process context.
  */
-static int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
+int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
 {
 	struct Scsi_Host *host = cmd->host;
 	unsigned long flags;
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sat Oct 26 19:46:01 2002
+++ b/drivers/scsi/scsi.h	Sat Oct 26 19:46:01 2002
@@ -480,6 +480,7 @@
 			void (*done) (struct scsi_cmnd *),
 			int timeout, int retries);
 extern int scsi_dev_init(void);
+extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
 
 /*
  * Newer request-based interfaces.
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sat Oct 26 19:46:01 2002
+++ b/drivers/scsi/scsi_lib.c	Sat Oct 26 19:46:01 2002
@@ -1005,7 +1005,8 @@
 		req = NULL;
 		spin_unlock_irq(q->queue_lock);
 
-		if (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+		if (!(SCpnt->request->flags & REQ_DONTPREP)
+		    && (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC))) {
 			/*
 			 * This will do a couple of things:
 			 *  1) Fill in the actual SCSI command.
@@ -1026,18 +1027,8 @@
 			 * required).
 			 */
 			if (!scsi_init_io(SCpnt)) {
+				scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
 				spin_lock_irq(q->queue_lock);
-				SHpnt->host_busy--;
-				SDpnt->device_busy--;
-				if (SDpnt->device_busy == 0) {
-					SDpnt->starved = 1;
-					SHpnt->some_device_starved = 1;
-				}
-				SCpnt->request->special = SCpnt;
-				SCpnt->request->flags |= REQ_SPECIAL;
-				if(blk_rq_tagged(SCpnt->request))
-					blk_queue_end_tag(q, SCpnt->request);
-				_elv_add_request(q, SCpnt->request, 0, 0);
 				break;
 			}
 
@@ -1058,6 +1049,7 @@
 				continue;
 			}
 		}
+		SCpnt->request->flags |= REQ_DONTPREP;
 		/*
 		 * Finally, initialize any error handling parameters, and set up
 		 * the timers for timeouts.

^ permalink raw reply

* Re: dsdt and more
From: Sérgio Monteiro Basto @ 2002-10-27  0:41 UTC (permalink / raw)
  To: acpi-devel
In-Reply-To: <1035676644.1476.18.camel-4/PLUo9XfK/yXfm4dIG/yWZHpeb/A1Y/@public.gmane.org>

> with this new verion this mesg disappears ;), know I don't have
> /proc/processor. 
> 
not know, I mean now I don't have /proc/processor.
 
the message 
" acpi_processor-0897 [21] acpi_processor_get_per: Unsupported address
space [127] (control_register) " 
disappears with acpi 200201022.



-------------------------------------------------------
This SF.net email is sponsored by: ApacheCon, November 18-21 in
Las Vegas (supported by COMDEX), the only Apache event to be
fully supported by the ASF. http://www.apachecon.com

^ permalink raw reply

* Re: PATCH: Support PCI device sorting (Re: PCI device order problem)
From: H. J. Lu @ 2002-10-27  0:25 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Alan Cox, Linux Kernel Mailing List
In-Reply-To: <3DBB2DB9.3000803@pobox.com>

On Sat, Oct 26, 2002 at 08:05:13PM -0400, Jeff Garzik wrote:
> Jeff Garzik wrote:
> 
> > s/__devinit/__init/ and the implementation looks ok to me
> 
> 
> 
> ...except if your patch can be called in hotplug paths...

There are plenty of __devini in arch/i386/kernel/pci-pc.c. I will leave
mine alone.


H.J.

^ permalink raw reply

* Re: rootfs exposure in /proc/mounts
From: Andreas Steinmetz @ 2002-10-27  0:22 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Alexander Viro, linux-kernel
In-Reply-To: <3DBAEC79.5050605@pobox.com>

Jeff Garzik wrote:
> Andreas Steinmetz wrote:
> 
>> Alexander Viro wrote:
>>
>>>
>>> On Sat, 26 Oct 2002, Andreas Steinmetz wrote:
>>>
>>>
>>>> Maybe I do oversee the obious but:
>>>>
>>>> can somebody please explain why rootfs is exposed in /proc/mounts (I 
>>>> do mean the "rootfs / rootfs rw 0 0" entry) and if there is a good 
>>>> reason for the exposure?
>>>
>>>
>>>
>>>
>>> Mostly the fact that it _is_ mounted and special-casing its removal from
>>> /proc/mounts is more PITA than it's worth.
>>>
>> Acceptable but somewhat sad as it confuses e.g. "umount -avt noproc" 
>> which is somewhat standard in shutdown/reboot scripts (using a 
>> softlink from /etc/mtab to /proc/mounts).
> 
> 
> 
> Bug 1 - don't softlink directly to /proc/mounts :)  embedded guys 
> typically do this, and you see why it bites you in the ass :)
> 
> Bug 2 - "noproc" clearly does not avoid ramfs mounts, which is rootfs's 
> filesystem type.  And more and more ramfs filesystems will be appearing, 
> so that should be taken into consideration.
> 
> Sounds like userspace slackness to me, and nothing that the kernel guys 
> need to worry about...
> 
Only if there's another method to retrieve all filesystems mounted from 
userspace from the kernel. Though this may not be your view of things it 
is the only way to ensure that one gets a valid mount list. And as 
/proc/mounts is an interface to userspace it is my opinion that in 
kernel private mounts that can't be modified from userspace don't need 
to be listed there. Not my decision, anyway.


^ permalink raw reply

* incremental pacthes and patches against kernel 2.4.19 released
From: Sérgio Monteiro Basto @ 2002-10-27  0:16 UTC (permalink / raw)
  To: acpi support; +Cc: acpi-devel

site updated  in
http://codecs.home.sapo.pt

thanks
Sérgio Basto




-------------------------------------------------------
This SF.net email is sponsored by: ApacheCon, November 18-21 in
Las Vegas (supported by COMDEX), the only Apache event to be
fully supported by the ASF. http://www.apachecon.com

^ permalink raw reply

* Re: PATCH: Support PCI device sorting (Re: PCI device order problem)
From: Alan Cox @ 2002-10-27  0:30 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: H. J. Lu, Linux Kernel Mailing List
In-Reply-To: <3DBB2DB9.3000803@pobox.com>

On Sun, 2002-10-27 at 01:05, Jeff Garzik wrote:
> Jeff Garzik wrote:
> 
> > s/__devinit/__init/ and the implementation looks ok to me
> 
> 
> 
> ...except if your patch can be called in hotplug paths...

We can't go around re-sorting the PCI devices. The pci lists are not
locked sanely as it is


^ permalink raw reply

* Re: PATCH: Support PCI device sorting (Re: PCI device order problem)
From: Jeff Garzik @ 2002-10-27  0:05 UTC (permalink / raw)
  To: H. J. Lu; +Cc: Alan Cox, Linux Kernel Mailing List
In-Reply-To: <3DBB2BE7.70208@pobox.com>

Jeff Garzik wrote:

> s/__devinit/__init/ and the implementation looks ok to me



...except if your patch can be called in hotplug paths...



^ permalink raw reply

* dsdt and more
From: Sérgio Monteiro Basto @ 2002-10-26 23:57 UTC (permalink / raw)
  To: acpi-devel

[-- Attachment #1: Type: text/plain, Size: 1887 bytes --]

I will report all strange things acpi related in my Compaq pressario
706EA. 


./iasl -tc -i acpi_dsdt.dsl 
give me this strange error, the others error have fixes. 
acpi_dsdt.dsl   549:                     Zero 
Error    1037 -                 parse error ^ 


if I override bios with this dsdt fixed deleting or not deleting this
Zeros, my BAT is not recognized. 
without override I can read BATTERY information. 

"Table [SSDT] - 0 Objects with 0 Devices 0 Methods 0 Regions" 


" acpi_processor-0897 [21] acpi_processor_get_per: Unsupported address
space [127] (control_register) 
ACPI: Processor [CPU0] (supports C1 C2, 16 throttling states)" 

with this new verion this mesg disappears ;), know I don't have
/proc/processor. 

acpidmp > dmp.bin 
acpidmp DSDT > DSDT.bin 
acpidmp FACP > FACP.bin 
acpidmp FACS > FACS.bin 
acpidmp FADT > FADT.bin 
acpidmp RSDP > RSDP.bin 
acpidmp RSDT > RSDT.bin 
acpidmp SSDT > SSDT.bin 
cat /proc/acpi/fadt > fadt.bin 

from dmesg: 
ACPI: RSDP (v000 PTLTD                      ) @ 0x000f6dd0 
ACPI: RSDT (v001 PTLTD    RSDT   01540.00000) @ 0x0defb63b 
ACPI: FADT (v001 COMPAQ  EAGLES  01540.00000) @ 0x0defeeb6 
ACPI: SSDT (v001 PTLTD  POWERNOW 01540.00000) @ 0x0defef2a 
ACPI: DSDT (v001 COMAPQ   EAGLES 01540.00000) @ 0x00000000 
ACPI: Vendor "COMAPQ" System "  EAGLES" Revision 0x6040000 has a known
ACPI BIOS problem. 
ACPI: Reason: SCI issues (C2 disabled). This is a recoverable error 
ACPI: BIOS passes blacklist 


and finally 
Oct 21 03:42:57 darkstar kernel: [ACPI Debug] String: USB runtime event 
Oct 21 03:42:57 darkstar kernel: acpi_bus-0263 [15]
acpi_bus_get_device   : Error getting context for object [cde28ee8] 
Oct 21 03:42:57 darkstar kernel: hub.c: USB new device connect on
bus1/1, assigned device number 3 
Oct 21 03:42:57 darkstar kernel: usb.c: USB device 3 (vend/prod
0x5ab/0x200) is not claimed by any active driver. 


[-- Attachment #2: bins.tar.gz --]
[-- Type: application/x-gzip, Size: 6345 bytes --]

^ permalink raw reply

* [LARTC] CBQ broken in RedHat 8.0?
From: Neil Aggarwal @ 2002-10-26 23:53 UTC (permalink / raw)
  To: lartc

Hello all:

Is CBQ broken in RedHat 8.0?
It seems that my CBQ is not using priorities.

I have this setup:

Internet <-> DSL Modem <-> Linux router <-> IP Switch <-> Laptop

The Linux computer is running a fresh, unmodified installation
of RedHat 8.0?

On the Linux computer, eth0 points to the DSL modem
and eth1 points to my internal network.
The Linux compter runs DHCP and masquerade.

I want to make sure that ssh traffic is prioritied above
all other traffic.

After reading the HOWTO and the wondershaper code, I set-up the following
tc rules on the Linux computer:

# The downlink speed, in kilobits
DOWNLINK00
# The uplink speed, in kilobits
UPLINK\x100
# The device to control
DEV=eth0
# Install the root CBQ at 1:0
tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit

# Add a cbq at 1:1 to limit the total bandwidth to the uplink speed
tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit allot
1500 prio 1 bounded isolated

# Create a queue for the high priority traffic
tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit allot
1600 prio 1 avpkt 1000 bounded isolated
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10

# Create a queue for the low priority traffic
tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $[9*$UPLINK/10]kbit
allot 1600 prio 2 avpkt 1000 bounded isolated
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

# Filter ssh traffic into the high prioirty queue
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip sport 22
0xffff  flowid 1:10
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip dport 22
0xffff  flowid 1:10

# Filter the rest of the traffic into the low priority queue, policing the
rate and dropping any overflow packets
tc filter add dev $DEV parent 1:0 protocol ip prio 13 u32 match ip dst
0.0.0.0/0 police rate $[9*$UPLINK/10]kbit burst 10k drop flowid 1:20

# Police the incoming traffic to the rate we specified
tc qdisc add dev $DEV handle ffff: ingress
tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src
0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1


What I am expecting from these rules is that the ssh traffic will take
complete priority over
anything else.  Other traffic will only get what is left over.

To test this, I set-up a large FTP upload from my laptop to a machine over
the Internet
and then set up and ssh transfer of a large file to another machine.
After letting things settle down, I ran my traffic control script.

After a while, I ran this command to see the results:
tc -s qdisc ls dev eth0

Here is what I got:
 qdisc ingress ffff: ----------------
 Sent 514549 bytes 9924 pkts (dropped 0, overlimits 0)

 qdisc sfq 20: quantum 1514b perturb 10sec
 Sent 10522893 bytes 7296 pkts (dropped 0, overlimits 0)
 backlog 5p

 qdisc sfq 10: quantum 1514b perturb 10sec
 Sent 7648142 bytes 5449 pkts (dropped 0, overlimits 0)

 qdisc cbq 1: rate 10Mbit (bounded,isolated) prio no-transmit
 Sent 18173599 bytes 12771 pkts (dropped 120, overlimits 18412)
 backlog 5p
  borrowed 0 overactions 0 avgidle 624 undertime 0

The low priority traffic is getting more traffic sent thru.
This is not what I wanted.

Any ideas why this is happening?

Thanks,
	Neil.


--
Neil Aggarwal
JAMM Consulting, Inc.    (972) 612-6056, http://www.JAMMConsulting.com
Custom Internet Development    Websites, Ecommerce, Java, databases

_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.