Mem5 13.7 KB
;>MEM5D_SCR
;
; RISC OS 2+ BOOT TEST SOFTWARE.
; MEMORY TEST 5 VERSION D.      BRIAN RICE 10-01-90.
; 04-Apr-90     ArtG    0.1     Use memory size to determine page count
; 11-Apr-90	ArtG	0.2	Changes to permit use of BangCam
;
; This file will be called by MEM6x_SCR for the purposes of assembly.
; This file requires the assembly of MEM4x_SCR to be perfromed at the
; same time. The program will call the cam setting routines in the cam
; test program.
;
; This file will test MEMCs ability to assert its protection over
; logical pages.
; The test code for this test was taken from the A680 test code.
; The Arm CPU has three mode of operation, Supervisor, Operating System.
; and User. Most of the time the machine will operate in user mode, in this.
; mode the designers do not want the user to have full access to the memory.
; map, therefore the MEMC(s) will check that the CPU has the appropiate
; level of authorisation to access specific area of memory.
; User mode is the lowest mode, allowing limited R/W access to the ram.
; Operating System is next up the list and is allowed some more access to
; to the ram than user mode.
; Supervisor mode this is the highest and the CPU has unlimited access to
; the entire memory map. 
;
; This version has the "my abort" routine in it not the ts_dab_exp0..5 routine as
; coded from the A680 code.
;
; Set up some variables.
;
ts_wks_word     *   36                      ; Offset of word for workspace.
;
; ****************************************************************************
;
ts_memc_prot
;
; This module will map and assign protection mode 0 to all the pages. The
; module will then perfrom a read and write operations in supervisor and
; user modes. This is repeated for the three (four) protection modes.
; The module will check after every protection mode level that the required
; responses have been returned.
;
; Set up the memory, map and assign protection mode 0.
;
        ROUT                                ; Local Branches.
        MOV     r13, lr                     ; Preserve the link register.
        MOV     r12, #&00                   ; r12 = The physical page to test.

0       ADD     r8, r12, #&01               ; Get a page to use as vectors,
	BL	ts_count_CAMs		    ; get total number of pages
	SUB	r0,r0,#1 		    ; make a mask for useable page
	AND	r0,r0,#&7f		    ; numbers - min(128, num_pages)
        AND     r8, r8, r0

        MOV     r1, r8                      ; r1 = r8,  r1 = physical page 0.
        MOV     r0, #&00                    ; r0 = &00, r0 = logical page 0.
        BL      ts_set_cam                  ; Gosub ts_set_cam, set the CAM up.
;
; Set protection mode 0 and test that page.
;
        MOV     r2, #&00                    ; r2 = &00, r2 = protection mode 0.
        BL      ts_mem_prot                 ; Gosub ts_mem_prot.
        CMP     r3,#&0F                     ; Is r3 = &0F ? r3 = Super Read/Write ok.
                                            ;                    O/S   Read/Write ok.
                                            ;                    User  Read/Write ok.
	MOV	r2, #0
        BNE     ts_prot_fail                ; If r3 <> &0F Then branch to fail routine.
;
; Set protection mode 1 and test that page.
;
        MOV     r2, #&01                    ; r2 = &01, r2 = protection mode 1.
        BL      ts_mem_prot                 ; Gosub ts_mem_prot.
	[ CPU_Type = "ARM600"
	CMP	r3,#&0f			    ; no ABORT line to ARM600
	|
	CMP     r3,#&0B                     ; Is r3 = &0B ? r3 = Super Read/Write ok.
	]                                   ;                    O/S   Read/Write ok.
                                            ;                    User  Read only ok.

	MOV	r2,#1
        BNE     ts_prot_fail                ; If r3 <> &0B Then branch to fail routine.
;
; Set protection mode 2 and test that page.
;
        MOV     r2, #&02                    ; r2 = &02, r2 = protection mode 2.
        BL      ts_mem_prot                 ; Gosub ts_mem_prot.
	[ CPU_Type = "ARM600"
	CMP	r3,#&0f			    ; no ABORT line to ARM600
	|
        CMP     r3,#&03                     ; Is r3 = &03 ? r3 = Super Read/Write ok.
	]                                   ;                    O/S   Read only ok.
                                            ;                    User  No Access ok. 
	MOV	r2,#2
        BNE     ts_prot_fail                ; If r3 <> &03 Then branch to fail routine.
;
; Set protection mode 3 and test that page.
;
        MOV     r2, #&03                    ; r2 = &03, r2 = protection mode 3.
        BL      ts_mem_prot                 ; Gosub ts_mem_prot.
	[ CPU_Type = "ARM600"
	CMP	r3,#&0f			    ; no ABORT line to ARM600
	|
        CMP     r3, #&03                    ; Is r3 = &03 ? r3 = Super Read/Write ok.
	]                                   ;                    O/S   Read only ok.
                                            ;                    User  No Access ok. 
	MOV	r2,#3
        BNE     ts_prot_fail                ; If r3 <> &03 Then branch to 
                                            ; fail routine.
;
; Reset the page used to idle.
;
        MOV     r0, r12                     ; r0 = r12, idle the pages 
                                            ; being used.
        BL      ts_set_cam_idle             ; Gosub ts_set_cam_idle.
        MOV     r0, r8                      ; r0 = r8, idle the pages 
                                            ; being used. 
        BL      ts_set_cam_idle             ; Gosub ts_set_cam_idle.
;
; Increment the physical page counter and check that all the pages are 
; done, else finish.
;
        BL      ts_count_CAMs
        ADD     r12, r12, #&01              ; do the next physical page.
        CMP     r12, r0                     ; Done all pages ?
        BLT     %B0                         ; If r12 <= cam_entries, 
                                            ; branch back to 0.

        ANDS    r0, r0, #0                  ; set zero flag : test passed
        MOV     pc, r13                     ; Return to caller.
;
; **************************************************************************
;
; Branch here when ts_memc_prot fails to get the proper result from
; ts_mem_prot.
;
; At this point, 
;                 
; r3  is a map of permitted ops (user read, user write, sys read, sys write) 
; r2  is the memc protection mode
; r12 is the physical page number.
;
; This is displayed as :   
;
;       PPL bad l.a.pppp
;
; where l is the PPL set on that page (0, 1, 2 or 3)
;       a is a bitmap of the actual operations permitted (ur.uw.or.ow)
;       p is the physical page number tested
;

0
        =       "PPL bad",&88,&ff,".",&ff,".",&ff,&ff,&ff,&ff,0
        ALIGN

ts_prot_fail
        AND     r2, r2, #&0f
        MOV     r0, r2, LSL #20          ; mode bits
        AND     r3, r3, #&0f
        ORR     r0, r0, r3, LSL #16     ; permitted ops bits
        BIC     r12, r12, #&ff000000
        BIC     r12, r12, #&ff0000
        ORR     r0, r0, r12             ; current page number


        ADR     r4, %B0                 ; get fail message  
        MOV     r8, r0, LSL #8          ; shift number to suit ts_SendText
        ORRS    r0, r0, #1              ; fail flag
        MOV     pc, r13


;
;
; This section will test that the physical page referenced in r12 at the set 
; protection mode. During the operation of this module, aborts are expected to happen.
; The aborts are handled by the routine ts_dab.
;
; The system is running in supervisor mode and thus to check the user mode read / writes
; the address translator flag is used. The CPU has a signal called -TRANS which when used
; with MEMC forces the an address translation to be performed, this is not done whilst
; in supervisor mode because it has unlimited access to the memory map. The address
; translator falg (T) is used with STR and LDR instructions only, the effective result of
; adding the (T) to the opcode is to force the instruction to be executed as if the CPU
; was in user mode, thus unauthorised accesses will cause an abort to occur.
;
; IN:
;       r12 - physical page.
;       r2  - protection mode.
; OUT:
;       r3  - access pattern.
;             r3 = &0F, Super Read/Write ok, O/S Read/Write ok, User Read/Write ok.
;             r3 = &0B, Super Read/Write ok, O/S Read/Write ok, User Read only ok.
;             r3 = &03, Super Read/Write ok, O/S Read only ok,  User No Access ok.
;
ts_mem_prot
;
; Set up data to write and read from memory.
;
        MOV     r10, lr                     ; Preserve link register.
        MOV     r1, r12                     ; r1 = physical page.
        MOV     r0, #&01                    ; r0 = logical page 1.
        BL      ts_set_camp 

        MOV     r3, #&00                    ; Initialise access pattern.
	MOV_fiq	r5, r11_fiq		    ; get MEMC control
	AND	r5, r5, #&C
	ADR	r9, ts_ppl_tptrs
	LDR	r9, [r9, r5]		    ; get test address for this pagesize
;
; Test 1 system mode - write.
;
        MOV     r6, #&00                    ; r6 = &00, clear expected abort flag.
        MOV     r7, #&94                    ; r7 = &94, set abort expected flag.
;
; The following instruction may abort.
;
        STR     r1, [r9]                    ; Store r1 at loc pointed to by r9.
        CMP     r6, #&00                    ; Is r6 = &00 ? If not then abort happened.
        ORREQ   r3, r3, #&01                ; If r6 = &00, Then update r3, access pattern.
;
; Test 2 system mode - read.
;
        MOV     r6, #&00                    ; r6 = &00, clear expected abort flag.
        MOV     r7, #&94                    ; r7 = &94, set abort expected flag.
;
; The following instruction may abort.
;
        LDR     r1, [r9]                    ; Load r1 from loc pointed to by r9.
        CMP     r6, #&00                    ; Is r6 = &00 ? If not then abort happened.
        ORREQ   r3, r3, #&02                ; If r6 = &00 Then update r3, access pattern.
;
; Test 3 user mode - write.
;
        MOV     r6, #&00                    ; r6 = &00, clear expected abort flag.
        MOV     r7, #&94                    ; r7 = &94, set abort expected flag.
;
; The following instruction may abort.
;
        STRT    r1, [r9]                    ; Store r1 at loc pointed to by r9.
        CMP     r6, #&00                    ; Is r6 = &00 ? If not then abort happened.
        ORREQ   r3, r3, #&04                ; If r6 = &00 Then update r3, access pattern.
;
; Test 4 user mode - read.
;
        MOV     r6, #&00                    ; r6 = &00, clear expected abort flag.
        MOV     r7, #&94                    ; r7 = &94, set expected expected flag.
;
; The following instruction may abort.
;
        LDRT    r1, [r9]                    ; Load r1 from loc pointed to by r9.
        CMP     r6, #&00                    ; Is r6 = &00 ? If not then abort happened.
        ORREQ   r3, r3, #&08                ; If r6 = &00 Then update r3, access pattern.
        MOV     pc, r10                     ; Return to caller.

;
; addresses (a short way up page 1) to test PPL aborts
;

ts_ppl_tptrs
	&	( 4 * 1024) + ts_wks_word
	&	( 8 * 1024) + ts_wks_word
	&	(16 * 1024) + ts_wks_word
	&	(32 * 1024) + ts_wks_word
;
;
ts_dab
;
; This routine provides the handling when a DATA ABORT occurs.
; The routine will if the abort was DATA cause the program to skip over the instruction
; that caused the abort first place.
; Data aborts could come from a variety of sources, in this module we are only concerned
; about a select group of aborts. This abort routine is called instead of the "usuall"
; abort routine. All that is required from this abort routine is to set a flag to
; indicate that an abort occured. Therefore this routine needs to be told that the
; abort that caused the routine to be called is either one of mine or not, (expected
; or unexpected). To achive this &94 is placed in r7. The abort routine will check
; for the presence of &94 in r7, if present then the abort is an expected abort.
; The abort routine will then copy r7 into r6, which is used as a flag to indicate
; that an abort occured and that it was an expected abort. Then the routine will
; return control to the program at the location after the instruction that caused to
; abort to occur.
; The return address is stored by the CPU into the link regester lr (r14), sort off.
; It must be remembered that the PC is always 2 instructions ahead. E.G. if the
; instruction that causes the abort is at &2000, then the lr will have &2008 in it,
; but we want to return to the location after the abort instruction, &2004. Therefore to
; return to the correct location &04 is removed from the lr and this is put into the pc.
; If the abort was not expected then the routine will jump to the end and another
; routine will show that an unexpected abort was generated.
;
; IN:
;       r6 - Equals &00, cleared just before the instruction that could cause an abort.
;       r7 - Equals &94, set just before the instruction that could cause an abort.
;
; OUT:
;       r6 - Equals &94, set if an abort happened and was expected.
;       r7 - Equals &94, preserved.
;
        ROUT                                ; Local Branches.
;
; Check that it is an expected abort and not an unexpected abort.
;
        CMP     r7, #&94                    ; Is r7 = &94, abort expected value.
        BNE     ts_dab_unexp                ; If <> &94, Then branch to unexpected
                                            ; abort handler.
;
; It is an expected  abort, so handle it.
;
        MOV     r6, r7                      ; r6 = r7, indicates that an abort happened.
        SUB     pc, lr, #&04                ; pc = link reg - &04.
                                            ; Skip over aborting instruction.
                                            ; By reloading the pc we return to the area
                                            ; of code where the abort occured but 4
                                            ; locations further on.


 END