Re: GGI and cli/sti in X

Jean Wolter (jw5@os.inf.tu-dresden.de)
28 Mar 1998 16:48:06 +0200


alan@lxorguk.ukuu.org.uk (Alan Cox) writes:

>
> > I get 5 or 6 ughs everytime somone runs X onmy system so I'd say your
> > correct, the ughs are allways in do_page_fault. The ughs are normal on
> > any system I've seen with < 16 megs ram. The every once and a while
>
> The "Ugh" is logging the fact someone attempted to handle a page fault while
> having interrupts disabled. This is an extremely bad thing. There are two causes
>
> 1. Incorrect kernel code (I think most of these are now dead)
> 2. Some user process as root which has the misguided idea it can disable
> interrupts after using the iopl() syscall. Well it can't. Not unless
> its prepaged everything it needs and mlock()'d those pages
>
> so its either a kernel or an X bug.
>
> Alan

If this is a bug I would like to point out one place where such a bug
still exists:

static int rs_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
...
save_flags(flags);
while (1) {
cli();
...
if (from_user) {
c -= copy_from_user(tmp_buf, buf, c);
...
}
restore_flags(flags);
...
}

Under heavy load both X and gpm are raising page faults at this
place. Unfortunatly the Ugh is only generated by SMP kernels. I have
found this sequence only after inserting some statements that check
for disabled interrupts on non smp systems too. Maybe it would be a
good idee to insert such a check in both systems (smp and non smp).

Jean

PS:

The backtrace looks like that (2.1.91):

>>EIP: c019416a <__generic_copy_from_user+36/40>
Trace: c017b0ef <rs_write+10b/20c>
Trace: c016dd56 <write_chan+152/1d0>
Trace: c0169d75 <tty_write+121/178>
Trace: c016dd56 <write_chan+152/1d0>
Trace: c012373c <sys_write+b4/10c>
Trace: c010992a <system_call+3a/40>
Code: c019416a <__generic_copy_from_user+36/40>
Code: c019416a <__generic_copy_from_user+36/40> f3 a4 repz movsb %ds:(%esi),%es:(%edi)

The added check like that:

--- fault.c.orig Sat Mar 28 16:15:29 1998
+++ fault.c Sat Mar 28 16:15:00 1998
@@ -76,6 +76,7 @@
}

asmlinkage void do_invalid_op (struct pt_regs *, unsigned long);
+extern void show_registers(struct pt_regs *regs);

/*
* This routine handles page faults. It determines the address,
@@ -102,6 +103,13 @@

if (local_irq_count[smp_processor_id()])
die_if_kernel("page fault from irq handler",regs,error_code);
+
+ if (!(regs->eflags & 0x200)) {
+ printk("program %s raised page fault at eip %lx while interrupts disabled\n",
+ current->comm, regs->eip);
+ show_registers(regs);
+ }
+
lock_kernel();
tsk = current;
mm = tsk->mm;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu