Subject: locore?
To: None <tech-kern@NetBSD.ORG>
From: Andrew Cagney <cagney@highland.com.au>
List: tech-kern
Date: 06/30/1995 12:52:01
Hello,

My understanding of locore.s is that it provides two key services:

	o	entry point for booting kernel

	o	acting as a switch between interrupt
		and trap events and their kernel handlers

I've also noticed that some locore implementations contain things like
memmov().  I suspect, however that these functions ended up in locore.s
for the sake of convenience.

Anyway, following on from the second locore service noted above, the
table that follows lists what I understand to be both the cases that
locore should handle and their corresponding actions.

(But first some definitions:

Stacks:
	KS - kernel stack - a per-user-thread stack in the kernel address space
	IS - interrupt stack - a single stack for handling all interrupts

State:
	U - user - processor in user mode
	K - kernel - processor in kernel mode on users kernel stack
	I - interrupt - processor in kernel mode on interrupt stack

Events:
	int - something asynchronous and probably from the hardware
	trap - something from a user program (eg page fault, fp exception
	system call ...).  An example of a trap when in a trap handler
	would be a page fault.

	With traps, I'll ignore things like a TLB miss trap which should either
	a. be resolved within locore or b. converted to a page fault.

Save stack:
	Where locore should save the context of the interrupted thread.

Call stack:
	The stack that is used to call the higher level kernel C handlers
	(eg trap() or interrupt()).

Which interrupt handler?
	I ignore how to figure where an interrupt came from and where
	it should be dispatched to.

Check ast?
	Asynchronous Software Trap Flag is used to signal that, once all
	interrupts have been handled, instead of returning to user mode,
	a fake trap should occure (see daemon).

	In the below by maybe I mean that I don't think it is needed but
	probably wouldn't do any harm.

)

  STATE  EVENT  SAVE-STACK  CALL-STACK  CHECK-AST?

1. user  trap      KS        KS - trap    maybe
2. kern  trap      KS        KS - trap     no
3. intr  trap          ------- panic? ------

4. user  int       KS        IS - intr    yes
5. kern  int       IS        IS - intr     no
6. intr  int       IS        IS - intr     no


Following on from this, the following pseudo code would implement the above.

TRAP:
	save on (current) kernel stack
	call trap() on kernel stack (It can work out if to panic)

INTERRUPT:
	if old state == user
		save on kernel stack (so ready for ast)
		call interrupt()	on interrupt stack
		if ast flag
			clear ast flag
			call trap() on kernel stack
		return
	else
		save on interrupt stack
		call interrupt() on interrupt stack
		return
	fi

Following on from this:

Q2:	Is the table (although probably simplified) correct?

Q3:	Is the panic above (in the case of a trap on the interrupt stack)
	correct?

Q3a:	What about page faults on the interrupt stack?  I'm assuming
	that they can never occure.

Q4:	Could the ast flag be set while handling a trap.  If all else
	fails I could suck and see.

Q5:	I am correct in assuming that this kernel, when in a trap handler,
	(case 2 above) the kernel will still get (or fake) page fault traps
	so that user pages are loaded when a trap handler needs them.

Comments or corrections more than welcome.

			Andrew

[Ref: the daemon book]
[Ref: alpha source code]
[Ref: 68k source code]