cvs commit: src/sys/compat/ndis hal_var.h kern_ndis.c kern_windrv.c ndis_var.h ntoskrnl_var.h pe_var.h subr_hal.c

Bill Paul wpaul at FreeBSD.ORG
Mon Apr 11 18:15:20 PDT 2005


[Charset iso-8859-1 unsupported, filtering to ASCII...]
> On Monday 11 April 2005 02:54 pm, Julian Elischer wrote:
> > Bill Paul wrote:
> > >wpaul       2005-04-11 02:02:35 UTC
> > >
> > >
> > >  The twist has to do with the fact that Microsoft supports structured
> > >  exception handling in kernel mode. On the i386 arch, exception handling
> > >  is implemented by hanging an exception registration list off the
> > >  Thread Environment Block (TEB), and the TEB is accessed via the %fs
> > >  register. The problem is, we use %fs as a pointer to the pcpu stucture,
> > >  which means any driver that tries to write through %fs:0 will overwrite
> > >  the curthread pointer and make a serious mess of things.
> > >
> > >  To get around this, Project Evil now creates a special entry in
> > >  the GDT on each processor. When we call into Windows code, a context
> > >  switch routine will fix up %fs so it points to our new descriptor,
> > >  which in turn points to a fake TEB. When the Windows code returns,
> > >  or calls out to an external routine, we swap %fs back again. Currently,
> > >  Project Evil makes use of GDT slot 7, which is all 0s by default.
> > >  I fully expect someone to jump up and say I can't do that, but I
> > >  couldn't find any code that makes use of this entry anywhere. Sadly,
> > >  this was the only method I could come up with that worked on both
> > >  UP and SMP. (Modifying the LDT works on UP, but becomes incredibly
> > >  complicated on SMP.) If necessary, the context switching stuff can
> > >  be yanked out while preserving the convention calling wrappers.
> >
> > Maybe we could emulate $soft and use %fs as a thread pointer instead and
> > have pcpu
> > pointed to via that :-)
> 
> I think NDIS drivers want %fs to point to a Windows-specific structure rather 
> than a 'struct thread' so I don't think that would buy us anything except for 
> even more memory indirects when we do a pcpu lookup.

John is correct. %fs points to the Windows TEB. I haven't dug up the
exact structure definition for the TEB yet, but I know that the first
DWORD in the TEB structure is a pointer to the exception handler
list. So when Windows drivers do, say, mov %eax,%fs:0 and think
they're writing to the exception list pointer in struct TEB, they're
actually writing to curthread in struct pcpu.

Now, we could have dodged the bullet by modifying struct pcpu slightly
so that the first thing in is a dummy unused pointer, which would shift
curthread down out of the way. Then Windows drivers could scribble on
%fs:0 all they want and there'd be no problems. But I'm not about to
redefine a core OS structure just to make Windows drivers happy.

It also occured to me that what I could have done was save the
curthread pointer somewhere during the UNIX-to-Windows context
switch, let the drivers trash it, then restore it when switching
from Windows-to-UNIX again. But if an interrupt occured while the CPU
happened to be in 'Windows' context, there would be no way to restore
the curthread pointer before entering interrupt context (whereas %fs
is saved/restored when entering interrupt context).

-Bill

--
=============================================================================
-Bill Paul            (510) 749-2329 | Senior Engineer, Master of Unix-Fu
                 wpaul at windriver.com | Wind River Systems
=============================================================================
              <adamw> you're just BEGGING to face the moose
=============================================================================


More information about the cvs-src mailing list