[comp.sys.amiga.tech] Use of SuperState

mph@behemoth.phx.mcd.mot.com (Mark Huth) (05/31/89)

While working this weekend on my 2620 system I experienced a lot of
gurus.  In an attempt to isolate the cause, I wanted to turn of the
cache.  I don't have SetCPU yet, so I decided to try some real simple
assembly code.

INCLUDE "exec/types.i"
INCLUDE "exec/libraries.i"
INCLUDE "exec/????.i" - you know, the one where the function offsets
			get defined

AbsExecBase EQU 4
CacheOff EQU 8

start:
	movem.l d0-d7/a0-a6,-(a7)	save regs
	movea.l AbsExecBase.w,a6	sets exec lib base register
	callsys SuperState		get into supervisor mode
	moveq.l #CacheOff,d1		constant to disable cache
	movec   d1,cacr			write it to the cache control reg
	callsys UserState
	movem.l (a7)+,d0-d7/a0-a6
	rts


This program reliably gurus - 3 or 4, don't remember.  When I trace
into the code with Lattice CPR, I lose it when the trap occurs - not
real surprising.  But looking at the code that is disasembled in the
trap handler, this should work great.  I've tried not tracing through
the exec call, but I never get control back from the SuperState call -
it's always off to the guru.

Is there a secret that I'm missing?

Thank You,
Mark Huth

daveh@cbmvax.UUCP (Dave Haynie) (05/31/89)

in article <10975@behemoth.phx.mcd.mot.com>, mph@behemoth.phx.mcd.mot.com (Mark Huth) says:
> Keywords: supervisor guru
> 
> While working this weekend on my 2620 system I experienced a lot of
> gurus.  In an attempt to isolate the cause, I wanted to turn of the
> cache.  

It's probably nothing to do with the cache; more on that in a bit...

> I've tried not tracing through the exec call, but I never get control 
> back from the SuperState call - it's always off to the guru.

> Is there a secret that I'm missing?

Yup.  For starters, UserState() is broken, at least on 68020/30 machines.
So you can never get back that way.  Here's how I do it in SetCPU:

	LVOSupervisor	EQU	-30

	;======================================================================
	;
	;	This function sets the value of the 68020/68030 CACR register.  
	;	It assumes a 68020 or 68030 based system.
	;
	;	void SetCACR(cacr)
	;	ULONG cacr;
	;
	;======================================================================

	_SetCACR:
		move.l	4(sp),d0		; New CACR is on stack
	 	move.l	4,a6			; Get ExecBase
		btst.b	#AFB_68020,ATNFLGS(a6)	; Does the OS think an '020 is here?
		bne	1$
		rts				; No CACR here, pal
	1$
		move.l	a5,-(sp)		; Save this register
		lea	2$,a5			; Get the start of the supervisor code
		CALLSYS	Supervisor
		move.l	(sp)+,a5		; Give it back
		rts
	2$
		movec	d0,cacr			; Set the CACR
		rte

Note that the Supervisor function isn't often mentioned.  I figure the main 
reason for that is that, as it's exited via RTE instead of RTS, it can't be
called directly from C.  In any case, this method will work on your A2620.

If you installed your A2620 yourself, and you're using a DMA driven hard
drive, you may have a known problem.  A2000s built with a 74ALS245 bus driver
chip made by Signetics at the U605 position can run into trouble with DMA
and an A2620 or possibly any other fast Coprocessor card that supports DMA
into it's fast memory.  The problem is that with the Signetics part, a
critical expansion bus signal doesn't get pulled up fast enough at the end
of a DMA transfer.  Changing the buffer chip would of course fix the problem,
but the suggested fix (dealers are supposed to know this) is to add a 3.3k
pullup resistor to the signal in question.  This resistor goes between pin
20 and pin 11 of U605.  The Signetics part can be identified by a big "S"
on it; no other manufacturer's part has shown any signs of this problem.

> Thank You,
> Mark Huth
-- 
Dave Haynie  "The 32 Bit Guy"     Commodore-Amiga  "The Crew That Never Rests"
   {uunet|pyramid|rutgers}!cbmvax!daveh      PLINK: D-DAVE H     BIX: hazy
              Amiga -- It's not just a job, it's an obsession

451061@UOTTAWA.BITNET (Valentin Pepelea) (06/01/89)

Mark Huth <mph@behemoth.phx.mcd.mot.com> writes in
Message-ID: <10975@behemoth.phx.mcd.mot.com>

> start:
>     movem.l d0-d7/a0-a6,-(a7)    save regs
>     movea.l AbsExecBase.w,a6    sets exec lib base register
>     callsys SuperState        get into supervisor mode
>     moveq.l #CacheOff,d1        constant to disable cache
>     movec   d1,cacr            write it to the cache control reg
>     callsys UserState
>     movem.l (a7)+,d0-d7/a0-a6
>     rts
>
> ...it's always off to the guru.
> Is there a secret that I'm missing?

The SuperState() & UserState() combo does not work. Use Supervisor() instead:

      movem.l a5,-(sp)
      movea.l ExecBase,a6
      lea.l   1$,a5
      CALLSYS Supervisor
      movem.l (sp)+,a5
      rts
1$
      moveq.l #CacheOff,d1
      move    d1,cacr
      rte

I've written replacement routines for SuperState() & UserState() which I use
in my code. They'll get published eventually. By the way, these two routines
are useful only with compilers which allocate variables on the stack. Lattice
C uses the LINK instruction to reserve space on the stack, and then references
that space through a5, so you do not need the two above routines, just use
Supervisor() instead. Remeber to always inspect the code produced by compilers
if you use assembler stubs with them.

Valentin
_________________________________________________________________________
"An  operating  system  without         Name:   Valentin Pepelea
 virtual memory is an operating         Phonet: (613) 231-7476 (New!)
 system without virtue."                Bitnet: 451061@Uottawa.bitnet
                                        Usenet: Use cunyvm.cuny.edu gate
         - Ancient Inca Proverb         Planet: 451061@acadvm1.UOttawa.CA

mph@behemoth.phx.mcd.mot.com (Mark Huth) (06/07/89)

In article <8906010307.AA11892@jade.berkeley.edu> 451061@UOTTAWA.BITNET (Valentin Pepelea) writes:
>
>The SuperState() & UserState() combo does not work. Use Supervisor() instead:
>
Thanks to Dave and Valentin for replies.  Specifically, the UserState call does
not work.  It dummies up a stack frame by using the same code that SuperState
uses.  However, SuperState, in the instance in question, would return with
an RTE, UserState returns by poping the SR and then doing an RTS - leaving the
dummied format/vector word on the stack for the next rts to stumble over.

Nice Job. 8-)   Actually, both routines are needlessly complex.  I stepped
through them with the ROM-wack this weekend.

Mark Huth

451061@UOTTAWA.BITNET (Valentin Pepelea) (06/13/89)

Mark Huth <mph@behemoth.phx.mcd.mot.com> writes in
Message-ID: <11022@behemoth.phx.mcd.mot.com>

> Thanks to Dave and Valentin for replies.  Specifically, the UserState call
> does not work.  It dummies up a stack frame by using the same code that
> SuperState uses.  However, SuperState, in the instance in question, would
> return with an RTE, UserState returns by poping the SR and then doing an
> RTS - leaving the dummied format/vector word on the stack for the next rts
> to stumble over.

Nice work, but now that you have identified the problem, why don't you fix it?
Heh, I'm gonna do it for you. Here is the SuperState() source code:

_UserState:                             ; void UserState(systack)(d0)

           move.l     a5,a0             ; Save this register
           lea        0$(pc),a5         ; Where to go in supervisor mode
           CALLSYS    Supervisor        ; Enter supervisor mode (just in case)
0$
           move.l     a0,a5             ; Restore a5
           move.w     (sp)+,d1          ; Get status register from stack
           move.l     sp,usp            ; Copy supervisor sp to user sp
           bclr       #$0D,d1           ; Clear supervisor bit
           move.l     d1,sr             ; Make it the current status register
           rts

When the execution is about to proceed to local label 0$, the current stack
contains the following:

!                !               !                !
! old status reg !               ! old status reg !
!----------------!               !----------------!
! return address !               ! return address !
!----------------!               !----------------!
! return address !               !   frame type   !
!----------------!               !----------------!
                                 ! return address !
      68000                      !----------------!

                                       68010+


The problem is that the call to Supervisor() places a (dummy) stack frame on
the supervisor stack, and this stack frame is slightly different for the
68010+ processors. They also place the frame type identifier on the stack.
So all we have to do is to ckech what processor we have before performing
an rts. Simply replace the rts above by:

           btst       #0,$0129(a6)      ; Running on a 68000?
           beq        1$                ; Branch if yes
           rtd        #2                ; Discard frame type and return
1$
           rts

I did not test this, but it certainly should work.

> Nice Job. 8-)   Actually, both routines are needlessly complex.  I stepped
> through them with the ROM-wack this weekend.

I disagree with that. There really is no simpler method to do this. Note that
there still is a bug in these calls; you can not nest them.

Hey, Commodore, now that I fixed UserState(), what do I get in return?

Valentin
_________________________________________________________________________
"An  operating  system  without         Name:   Valentin Pepelea
 virtual memory is an operating         Phonet: (613) 231-7476 (New!)
 system without virtue."                Bitnet: 451061@Uottawa.bitnet
                                        Usenet: Use cunyvm.cuny.edu gate
         - Ancient Inca Proverb         Planet: 451061@acadvm1.UOttawa.CA

doug@xdos.UUCP (Doug Merritt) (06/13/89)

In article <8906122208.AA17423@jade.berkeley.edu> 451061@UOTTAWA.BITNET (Valentin Pepelea) writes:
>Hey, Commodore, now that I fixed UserState(), what do I get in return?

As a corporation, unfortunately Commodore doesn't care about such
things.

But many of us *individuals* (including some at CATS) appreciate this
sort of thing.

So on behalf of the Usenet community, let me be the first to say:

	Atta boy! Way to go!

How's that?
	Doug
-- 
Doug Merritt		{pyramid,apple}!xdos!doug
Member, Crusaders for a Better Tomorrow		Professional Wildeyed Visionary

451061@UOTTAWA.BITNET (Valentin Pepelea) (06/16/89)

Doug Merritt <doug@xdos.uucp> writes in message <381@xdos.UUCP>

>   Atta boy! Way to go!
>   How's that?

How about hiring me?  :-)

Valentin
_________________________________________________________________________
"An  operating  system  without         Name:   Valentin Pepelea
 virtual memory is an operating         Phonet: (613) 231-7476 (New!)
 system without virtue."                Bitnet: 451061@Uottawa.bitnet
                                        Usenet: Use cunyvm.cuny.edu gate
         - Ancient Inca Proverb         Planet: 451061@acadvm1.UOttawa.CA

bryce@cbmvax.UUCP (Bryce Nesbitt) (06/27/89)

In article <10975@behemoth.phx.mcd.mot.com> mph@behemoth.UUCP (Mark Huth) writes:
>start:
>	movem.l d0-d7/a0-a6,-(a7)	save regs
>	movea.l AbsExecBase.w,a6	sets exec lib base register
>	callsys SuperState		get into supervisor mode
>	moveq.l #CacheOff,d1		constant to disable cache
>	movec   d1,cacr			write it to the cache control reg
>	callsys UserState
>	movem.l (a7)+,d0-d7/a0-a6
>	rts
>
>
>This program reliably gurus - 3 or 4, don't remember....
>...Is there a secret that I'm missing?

Yes.  The UserState() function does not work on 68010 or 68020 systems.
This is documented in more recent Exec autodocs.  The next revision of
the SetPatch program will fix this bug.

Use the Supervisor() function instead.  Supervisor will trap to a
short super-level exception function:

	...
	movea.l AbsExecBase.w,a6	sets exec lib base register
	lea.l	SuperCode(pc),a5
	moveq.l #CacheOff,d1		constant to disable cache
	callsys	Supervisor
	...

SuperCode:
	movec   d1,cacr			write it to the cache control reg
	rte





****************************************************************************
		New, official documentation for Exec call.  Works 
		and is blessed for use under all revisions of Amiga Kickstart
****************************************************************************


exec.library/Supervisor 			     exec.library/Supervisor

   NAME
	Supervisor -- trap to a short supervisor mode function

   SYNOPSIS
	result = Supervisor(userFunc)
	Rx                   A5
	ULONG Supervisor(void *);

   FUNCTION
	Execute a short assembly language function in the supervisor mode
	of the processor.  Supervisor() does not modify or save registers;
	the user function has full access to the register set.   All rules
	that apply to interrupt code must be followed.  In addition, no system
	calls are permitted.  The function must end with an RTE instruction.

   EXAMPLE
		;Obtain the Exception Vector base.  68010 or greater only!
		MOVECtrap:	movec.l	VBR,d0	;$4e7a,$0801
				rte

   INPUTS
	userFunc - A pointer to a short assembly language function ending
		  in RTE.  The function has full access to the register set.

   RESULTS
	result   - Whatever values the userFunc left in the registers.

   SEE ALSO
	SuperState/UserState

-- 
|\_/|  . ACK!, NAK!, EOT!, SOH!
{O o} .     Bryce Nesbitt, Commodore-Amiga, Inc.
 (")        BIX: bnesbitt
  U	    USENET: cbmvax!bryce@uunet.uu.NET -or- rutgers!cbmvax!bryce
Lawyers: America's untapped export market.