update: this may not work. From news:<b87095$6qkqb$1@ID-163150.news.dfncis.de>
    Yup, the TLB is flushed the very moment you modify PG or PE in CR0 
    (Intel Manual 3, 10.9.). No chance there :)


From: Frank Lofaro (ftlofaro@unlv.edu)
Subject: Re: Kernel flow of control
Newsgroups: comp.os.linux.development.system
Date: 1995-03-11 18:26:35 PST

In article <D50GCt.CnG@news.research.ptt.nl> leonb@sparta.research.ptt.nl (Bouwmeester L.) writes:
$[snip-snap]
$
$>#Reason: upon a context switch, besides the usual stuff, the TLB is flushed
$>#if a context switchs occurs between to kernel threads belonging to the same
$>#process. Problem is how to avoid that from happening. Probably the best
$>#thing to do is not to jump to the call-gate at all, but to perform some
$>#magical stuff when leaving the kernel (instead of restoring the registers
$>#of the original thread, restore the registers of the new one). Only in case
$>#of a context switch between 2 different processes when could jump to the
$>#call gate. But then again, this is not really the solution I was searching
$>#for. I'm wondering how this is done in QNX, as they have an excellent
$>#performance in context switching between threads.
$>
$>Could one have threads share the same page-tables and not change CR3?
$>Then the TLB isn't flushed. And when you need to invalidate TLB
$>entries on a 486 or better, use INVLPG instead of flushing the whole
$>TLB.
$
$I'm wondering whether this can be done that easily. Shall have to look at
$the capabilities of hardware and kernel source code real carefully. But
$then again, for now this is just a performance issue. I probably shall do
$such things later. But how'bout 386 (I have one, believe it or not)??

A 386 has a TLB but not INVLPG, but there may be a way to avoid a full
TLB flush...

The following might be considered disgusting, but hopefully it will be
useful. Here goes.. On the 386, you CAN manually kill page table
entries. Jump to an identity mapped part of memory, flip off paging,
use TR6 and TR7 (yes the TLB TEST registers) to mark that TLB entry as
invalid, flip on paging and return. Turn off interrupts while doing
this! (or BAD things will happen)

It should be less of a hit than a full TLB flush.

It should only be used on 386's and an existence test for TLB TEST
registers and proper functionality should be done first, like on
bootup. E.G. load 2 pages with different data, access one, change the
page tables in memory to point to the other, do the trick, and see if
accesses are properly rerouted to the new page (do this with
interrupts off!)
