cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

skeleton.S (11818B)


      1|
      2|	skeleton.sa 3.2 4/26/91
      3|
      4|	This file contains code that is system dependent and will
      5|	need to be modified to install the FPSP.
      6|
      7|	Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
      8|	Put any target system specific handling that must be done immediately
      9|	before the jump instruction.  If there no handling necessary, then
     10|	the 'fpsp_xxxx' handler entry point should be placed in the exception
     11|	table so that the 'jmp' can be eliminated. If the FPSP determines that the
     12|	exception is one that must be reported then there will be a
     13|	return from the package by a 'jmp real_xxxx'.  At that point
     14|	the machine state will be identical to the state before
     15|	the FPSP was entered.  In particular, whatever condition
     16|	that caused the exception will still be pending when the FPSP
     17|	package returns.  Thus, there will be system specific code
     18|	to handle the exception.
     19|
     20|	If the exception was completely handled by the package, then
     21|	the return will be via a 'jmp fpsp_done'.  Unless there is
     22|	OS specific work to be done (such as handling a context switch or
     23|	interrupt) the user program can be resumed via 'rte'.
     24|
     25|	In the following skeleton code, some typical 'real_xxxx' handling
     26|	code is shown.  This code may need to be moved to an appropriate
     27|	place in the target system, or rewritten.
     28|
     29
     30|		Copyright (C) Motorola, Inc. 1990
     31|			All Rights Reserved
     32|
     33|       For details on the license for this file, please see the
     34|       file, README, in this same directory.
     35
     36|
     37|	Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
     38|
     39
     40#include <linux/linkage.h>
     41#include <asm/entry.h>
     42#include <asm/asm-offsets.h>
     43
     44|SKELETON	idnt    2,1 | Motorola 040 Floating Point Software Package
     45
     46	|section 15
     47|
     48|	The following counters are used for standalone testing
     49|
     50
     51	|section 8
     52
     53#include "fpsp.h"
     54
     55	|xref	b1238_fix
     56
     57|
     58|	Divide by Zero exception
     59|
     60|	All dz exceptions are 'real', hence no fpsp_dz entry point.
     61|
     62	.global	dz
     63	.global	real_dz
     64dz:
     65real_dz:
     66	link		%a6,#-LOCAL_SIZE
     67	fsave		-(%sp)
     68	bclrb		#E1,E_BYTE(%a6)
     69	frestore	(%sp)+
     70	unlk		%a6
     71
     72	SAVE_ALL_INT
     73	GET_CURRENT(%d0)
     74	movel	%sp,%sp@-		| stack frame pointer argument
     75	bsrl	trap_c
     76	addql	#4,%sp
     77	bral	ret_from_exception
     78
     79|
     80|	Inexact exception
     81|
     82|	All inexact exceptions are real, but the 'real' handler
     83|	will probably want to clear the pending exception.
     84|	The provided code will clear the E3 exception (if pending),
     85|	otherwise clear the E1 exception.  The frestore is not really
     86|	necessary for E1 exceptions.
     87|
     88| Code following the 'inex' label is to handle bug #1232.  In this
     89| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
     90| swapped out before taking the exception, the exception taken on
     91| return was inex, rather than the correct exception.  The snan, ovfl,
     92| and unfl exception to be taken must not have been enabled.  The
     93| fix is to check for E1, and the existence of one of snan, ovfl,
     94| or unfl bits set in the fpsr.  If any of these are set, branch
     95| to the appropriate  handler for the exception in the fpsr.  Note
     96| that this fix is only for d43b parts, and is skipped if the
     97| version number is not $40.
     98|
     99|
    100	.global	real_inex
    101	.global	inex
    102inex:
    103	link		%a6,#-LOCAL_SIZE
    104	fsave		-(%sp)
    105	cmpib		#VER_40,(%sp)		|test version number
    106	bnes		not_fmt40
    107	fmovel		%fpsr,-(%sp)
    108	btstb		#E1,E_BYTE(%a6)		|test for E1 set
    109	beqs		not_b1232
    110	btstb		#snan_bit,2(%sp) |test for snan
    111	beq		inex_ckofl
    112	addl		#4,%sp
    113	frestore	(%sp)+
    114	unlk		%a6
    115	bra		snan
    116inex_ckofl:
    117	btstb		#ovfl_bit,2(%sp) |test for ovfl
    118	beq		inex_ckufl
    119	addl		#4,%sp
    120	frestore	(%sp)+
    121	unlk		%a6
    122	bra		ovfl
    123inex_ckufl:
    124	btstb		#unfl_bit,2(%sp) |test for unfl
    125	beq		not_b1232
    126	addl		#4,%sp
    127	frestore	(%sp)+
    128	unlk		%a6
    129	bra		unfl
    130
    131|
    132| We do not have the bug 1232 case.  Clean up the stack and call
    133| real_inex.
    134|
    135not_b1232:
    136	addl		#4,%sp
    137	frestore	(%sp)+
    138	unlk		%a6
    139
    140real_inex:
    141
    142	link		%a6,#-LOCAL_SIZE
    143	fsave		-(%sp)
    144not_fmt40:
    145	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
    146	beqs		inex_cke1
    147|
    148| Clear dirty bit on dest resister in the frame before branching
    149| to b1238_fix.
    150|
    151	moveml		%d0/%d1,USER_DA(%a6)
    152	bfextu		CMDREG1B(%a6){#6:#3},%d0		|get dest reg no
    153	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
    154	bsrl		b1238_fix		|test for bug1238 case
    155	moveml		USER_DA(%a6),%d0/%d1
    156	bras		inex_done
    157inex_cke1:
    158	bclrb		#E1,E_BYTE(%a6)
    159inex_done:
    160	frestore	(%sp)+
    161	unlk		%a6
    162
    163	SAVE_ALL_INT
    164	GET_CURRENT(%d0)
    165	movel	%sp,%sp@-		| stack frame pointer argument
    166	bsrl	trap_c
    167	addql	#4,%sp
    168	bral	ret_from_exception
    169
    170|
    171|	Overflow exception
    172|
    173	|xref	fpsp_ovfl
    174	.global	real_ovfl
    175	.global	ovfl
    176ovfl:
    177	jmp	fpsp_ovfl
    178real_ovfl:
    179
    180	link		%a6,#-LOCAL_SIZE
    181	fsave		-(%sp)
    182	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
    183	bnes		ovfl_done
    184	bclrb		#E1,E_BYTE(%a6)
    185ovfl_done:
    186	frestore	(%sp)+
    187	unlk		%a6
    188
    189	SAVE_ALL_INT
    190	GET_CURRENT(%d0)
    191	movel	%sp,%sp@-		| stack frame pointer argument
    192	bsrl	trap_c
    193	addql	#4,%sp
    194	bral	ret_from_exception
    195
    196|
    197|	Underflow exception
    198|
    199	|xref	fpsp_unfl
    200	.global	real_unfl
    201	.global	unfl
    202unfl:
    203	jmp	fpsp_unfl
    204real_unfl:
    205
    206	link		%a6,#-LOCAL_SIZE
    207	fsave		-(%sp)
    208	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
    209	bnes		unfl_done
    210	bclrb		#E1,E_BYTE(%a6)
    211unfl_done:
    212	frestore	(%sp)+
    213	unlk		%a6
    214
    215	SAVE_ALL_INT
    216	GET_CURRENT(%d0)
    217	movel	%sp,%sp@-		| stack frame pointer argument
    218	bsrl	trap_c
    219	addql	#4,%sp
    220	bral	ret_from_exception
    221
    222|
    223|	Signalling NAN exception
    224|
    225	|xref	fpsp_snan
    226	.global	real_snan
    227	.global	snan
    228snan:
    229	jmp	fpsp_snan
    230real_snan:
    231	link		%a6,#-LOCAL_SIZE
    232	fsave		-(%sp)
    233	bclrb		#E1,E_BYTE(%a6)	|snan is always an E1 exception
    234	frestore	(%sp)+
    235	unlk		%a6
    236
    237	SAVE_ALL_INT
    238	GET_CURRENT(%d0)
    239	movel	%sp,%sp@-		| stack frame pointer argument
    240	bsrl	trap_c
    241	addql	#4,%sp
    242	bral	ret_from_exception
    243
    244|
    245|	Operand Error exception
    246|
    247	|xref	fpsp_operr
    248	.global	real_operr
    249	.global	operr
    250operr:
    251	jmp	fpsp_operr
    252real_operr:
    253	link		%a6,#-LOCAL_SIZE
    254	fsave		-(%sp)
    255	bclrb		#E1,E_BYTE(%a6)	|operr is always an E1 exception
    256	frestore	(%sp)+
    257	unlk		%a6
    258
    259	SAVE_ALL_INT
    260	GET_CURRENT(%d0)
    261	movel	%sp,%sp@-		| stack frame pointer argument
    262	bsrl	trap_c
    263	addql	#4,%sp
    264	bral	ret_from_exception
    265
    266
    267|
    268|	BSUN exception
    269|
    270|	This sample handler simply clears the nan bit in the FPSR.
    271|
    272	|xref	fpsp_bsun
    273	.global	real_bsun
    274	.global	bsun
    275bsun:
    276	jmp	fpsp_bsun
    277real_bsun:
    278	link		%a6,#-LOCAL_SIZE
    279	fsave		-(%sp)
    280	bclrb		#E1,E_BYTE(%a6)	|bsun is always an E1 exception
    281	fmovel		%FPSR,-(%sp)
    282	bclrb		#nan_bit,(%sp)
    283	fmovel		(%sp)+,%FPSR
    284	frestore	(%sp)+
    285	unlk		%a6
    286
    287	SAVE_ALL_INT
    288	GET_CURRENT(%d0)
    289	movel	%sp,%sp@-		| stack frame pointer argument
    290	bsrl	trap_c
    291	addql	#4,%sp
    292	bral	ret_from_exception
    293
    294|
    295|	F-line exception
    296|
    297|	A 'real' F-line exception is one that the FPSP isn't supposed to
    298|	handle. E.g. an instruction with a co-processor ID that is not 1.
    299|
    300|
    301	|xref	fpsp_fline
    302	.global	real_fline
    303	.global	fline
    304fline:
    305	jmp	fpsp_fline
    306real_fline:
    307
    308	SAVE_ALL_INT
    309	GET_CURRENT(%d0)
    310	movel	%sp,%sp@-		| stack frame pointer argument
    311	bsrl	trap_c
    312	addql	#4,%sp
    313	bral	ret_from_exception
    314
    315|
    316|	Unsupported data type exception
    317|
    318	|xref	fpsp_unsupp
    319	.global	real_unsupp
    320	.global	unsupp
    321unsupp:
    322	jmp	fpsp_unsupp
    323real_unsupp:
    324	link		%a6,#-LOCAL_SIZE
    325	fsave		-(%sp)
    326	bclrb		#E1,E_BYTE(%a6)	|unsupp is always an E1 exception
    327	frestore	(%sp)+
    328	unlk		%a6
    329
    330	SAVE_ALL_INT
    331	GET_CURRENT(%d0)
    332	movel	%sp,%sp@-		| stack frame pointer argument
    333	bsrl	trap_c
    334	addql	#4,%sp
    335	bral	ret_from_exception
    336
    337|
    338|	Trace exception
    339|
    340	.global	real_trace
    341real_trace:
    342	|
    343	bral	trap
    344
    345|
    346|	fpsp_fmt_error --- exit point for frame format error
    347|
    348|	The fpu stack frame does not match the frames existing
    349|	or planned at the time of this writing.  The fpsp is
    350|	unable to handle frame sizes not in the following
    351|	version:size pairs:
    352|
    353|	{4060, 4160} - busy frame
    354|	{4028, 4130} - unimp frame
    355|	{4000, 4100} - idle frame
    356|
    357|	This entry point simply holds an f-line illegal value.
    358|	Replace this with a call to your kernel panic code or
    359|	code to handle future revisions of the fpu.
    360|
    361	.global	fpsp_fmt_error
    362fpsp_fmt_error:
    363
    364	.long	0xf27f0000	|f-line illegal
    365
    366|
    367|	fpsp_done --- FPSP exit point
    368|
    369|	The exception has been handled by the package and we are ready
    370|	to return to user mode, but there may be OS specific code
    371|	to execute before we do.  If there is, do it now.
    372|
    373|
    374
    375	.global	fpsp_done
    376fpsp_done:
    377	btst	#0x5,%sp@		| supervisor bit set in saved SR?
    378	beq	.Lnotkern
    379	rte
    380.Lnotkern:
    381	SAVE_ALL_INT
    382	GET_CURRENT(%d0)
    383	| deliver signals, reschedule etc..
    384	jra	ret_from_exception
    385
    386|
    387|	mem_write --- write to user or supervisor address space
    388|
    389| Writes to memory while in supervisor mode.  copyout accomplishes
    390| this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
    391| If you don't have copyout, use the local copy of the function below.
    392|
    393|	a0 - supervisor source address
    394|	a1 - user destination address
    395|	d0 - number of bytes to write (maximum count is 12)
    396|
    397| The supervisor source address is guaranteed to point into the supervisor
    398| stack.  The result is that a UNIX
    399| process is allowed to sleep as a consequence of a page fault during
    400| copyout.  The probability of a page fault is exceedingly small because
    401| the 68040 always reads the destination address and thus the page
    402| faults should have already been handled.
    403|
    404| If the EXC_SR shows that the exception was from supervisor space,
    405| then just do a dumb (and slow) memory move.  In a UNIX environment
    406| there shouldn't be any supervisor mode floating point exceptions.
    407|
    408	.global	mem_write
    409mem_write:
    410	btstb	#5,EXC_SR(%a6)	|check for supervisor state
    411	beqs	user_write
    412super_write:
    413	moveb	(%a0)+,(%a1)+
    414	subql	#1,%d0
    415	bnes	super_write
    416	rts
    417user_write:
    418	movel	%d1,-(%sp)	|preserve d1 just in case
    419	movel	%d0,-(%sp)
    420	movel	%a1,-(%sp)
    421	movel	%a0,-(%sp)
    422	jsr		copyout
    423	addw	#12,%sp
    424	movel	(%sp)+,%d1
    425	rts
    426|
    427|	mem_read --- read from user or supervisor address space
    428|
    429| Reads from memory while in supervisor mode.  copyin accomplishes
    430| this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
    431| If you don't have copyin, use the local copy of the function below.
    432|
    433| The FPSP calls mem_read to read the original F-line instruction in order
    434| to extract the data register number when the 'Dn' addressing mode is
    435| used.
    436|
    437|Input:
    438|	a0 - user source address
    439|	a1 - supervisor destination address
    440|	d0 - number of bytes to read (maximum count is 12)
    441|
    442| Like mem_write, mem_read always reads with a supervisor
    443| destination address on the supervisor stack.  Also like mem_write,
    444| the EXC_SR is checked and a simple memory copy is done if reading
    445| from supervisor space is indicated.
    446|
    447	.global	mem_read
    448mem_read:
    449	btstb	#5,EXC_SR(%a6)	|check for supervisor state
    450	beqs	user_read
    451super_read:
    452	moveb	(%a0)+,(%a1)+
    453	subql	#1,%d0
    454	bnes	super_read
    455	rts
    456user_read:
    457	movel	%d1,-(%sp)	|preserve d1 just in case
    458	movel	%d0,-(%sp)
    459	movel	%a1,-(%sp)
    460	movel	%a0,-(%sp)
    461	jsr	copyin
    462	addw	#12,%sp
    463	movel	(%sp)+,%d1
    464	rts
    465
    466|
    467| Use these routines if your kernel doesn't have copyout/copyin equivalents.
    468| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
    469| and copyin overwrites SFC.
    470|
    471copyout:
    472	movel	4(%sp),%a0	| source
    473	movel	8(%sp),%a1	| destination
    474	movel	12(%sp),%d0	| count
    475	subl	#1,%d0		| dec count by 1 for dbra
    476	movel	#1,%d1
    477
    478|	DFC is already set
    479|	movec	%d1,%DFC		| set dfc for user data space
    480moreout:
    481	moveb	(%a0)+,%d1	| fetch supervisor byte
    482out_ea:
    483	movesb	%d1,(%a1)+	| write user byte
    484	dbf	%d0,moreout
    485	rts
    486
    487copyin:
    488	movel	4(%sp),%a0	| source
    489	movel	8(%sp),%a1	| destination
    490	movel	12(%sp),%d0	| count
    491	subl	#1,%d0		| dec count by 1 for dbra
    492	movel	#1,%d1
    493|	SFC is already set
    494|	movec	%d1,%SFC		| set sfc for user space
    495morein:
    496in_ea:
    497	movesb	(%a0)+,%d1	| fetch user byte
    498	moveb	%d1,(%a1)+	| write supervisor byte
    499	dbf	%d0,morein
    500	rts
    501
    502	.section .fixup,#alloc,#execinstr
    503	.even
    5041:
    505	jbsr	fpsp040_die
    506	jbra	.Lnotkern
    507
    508	.section __ex_table,#alloc
    509	.align	4
    510
    511	.long	in_ea,1b
    512	.long	out_ea,1b
    513
    514	|end