Subject: NetBSD multi-threaded?

From: [email-masked] (Gordon W. Ross)

> Date: Mon, 12 Sep 1994 23:22:01 -0400
> From: "Chris G. Demetriou" <[email-masked]>

> charles said:
> > In Net/2 and later, the struct user is now stored in a per-process
> > location, not a fixed location for all processes.
> 
> Actually...  In Net/2 and later, each process has its own 'struct
> user' location, but (at least as far as i'm aware) when a process is
> curproc, its user struct is doubly-mapped to a constant address as
> well.  That's definitely true of all the ports that i'm aware of (but
> then, i'm not familiar with the low-level details of them all).
> 
> The reason for this is rather interesting: when you fork, you've gotta
> copy the kernel stack.  the kernel stack typically lives at the 'high
> end' of the UPAGES, and the per-process struct user lives at the low
> end.  It's really a pain to have to re-thread the stack, so, by
> remapping the UPAGES at a fixed address for all processes, and only
> using the kernel stack in that mapping, a lot of hassle is avoided...

On a related note, I was looking into implementing a "guard page"
for the kernel stack, and realized I can not easily do it with the
current layout of UPAGES.  For a guard page, I would like to have
the kernel stack at the beginning of the UPAGES and the struct user
at the end (at least on a machine where stacks grow downward).
This way, kernel stack overflow touches an invalid page instead of
trashing the user struct.  Currently, fork "knows" this layout...

One scheme I've seen for declaring the UPAGES like I want is:

#include <sys/user.h>
/* This is a machine where the stack grows down. */
struct upages {
	char kstack[KERN_STACK_SIZE];
	struct user u;	/* traditional stuff from user.h */
};

The value of KERN_STACK_SIZE is computed such that struct upages
comes out to (UPAGES*NBPG) or a little less.

As a portability issue, struct upages should be defined in the
architecture-specific code to allow a weird, stack-grows-up-
machine to reverse teh order of the members of struct upages.
One could even add stuff, like the current struct pcb, or some
floating-point state, etc. to struct upages if desired.

Does anyone else care about guard pages?
Is there a better way to implement them?

Gordon

---

From: [email-masked] (Mike Hibler)

> From: [email-masked] (Gordon W. Ross)
> Date: Tue, 13 Sep 94 11:07:52 EDT
> To: [email-masked]
> Cc: [email-masked], [email-masked]
> Subject: NetBSD multi-threaded? 
> 
> ...
On the 68k (hp300), UPAGES was originally 3 with the idea that a guard
page would be placed between the kernel stack and the user struct.
However, there is a problem on the 68k.  If you make the guard page
no-access (or even read-only) you take an exception and the first thing
the processor does is push an exception frame on the currently active
supervisor stack which is now no-access or write-protected and you wind
up halting the CPU.  As far as I know, you always have to have a valid
supervisor SP.

Another thing to consider is that a kernel routine could allocate a
local data structure whose size is greater than 1 page and you could wind
up stepping right over the guard page and trashing something anyway.

> floating-point state, etc. to struct upages if desired.
The other solution is to seperate the k-stack for the user struct.
I think the only reason they are together is so that they can be swapped
in one chunk.

BTW: the PA-RISC has an upward-growing stack, one of a number of
interesting features that break "portable" O.S.es like Mach.

---

From: Anders Magnusson <[email-masked]>

> at the end (at least on a machine where stacks grow downward).
[deleted...]
> Is there a better way to implement them?
In VAX port, I relocated kernel stack at first, (it was easiest) but
now I double-map it on top of user stack. (much cheaper) In this uarea
which I have mapped myself there is an "red zone" directly above user
struct. I thought it was easy way to implement stack protection.
/ragge