mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			478 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| ///////////////////////////////////////////
 | |
| // tlbmisc.S
 | |
| //
 | |
| // Written David_Harris@hmc.edu 1/1/24
 | |
| //
 | |
| // Purpose: Test coverage for other TLB issues
 | |
| //
 | |
| // A component of the CORE-V-WALLY configurable RISC-V project.
 | |
| // https://github.com/openhwgroup/cvw
 | |
| //
 | |
| // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
 | |
| //
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
 | |
| //
 | |
| // Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
 | |
| // except in compliance with the License, or, at your option, the Apache License version 2.0. You
 | |
| // may obtain a copy of the License at
 | |
| //
 | |
| // https://solderpad.org/licenses/SHL-2.1/
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, any work distributed under the
 | |
| // License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 | |
| // either express or implied. See the License for the specific language governing permissions
 | |
| // and limitations under the License.
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // load code to initalize stack, handle interrupts, terminate
 | |
| 
 | |
| #include "WALLY-init-lib.h"
 | |
| 
 | |
| # run-elf.bash find this in project description
 | |
| main:
 | |
|     li t5, 0x1
 | |
|     slli t5, t5, 62
 | |
|     ori t5, t5, 0xF0
 | |
|     csrs menvcfg, t5  # menvcfg.PBMTE = 1, CBZE, CBCFE, CBIE all 1
 | |
| 
 | |
|     # store ret instruction in case we jump to an address mapping to 80000000
 | |
|     li t0, 0x80000000
 | |
|     li t5, 0x8082 # return instruction opcode
 | |
|     sw t5, 0(t0)
 | |
|     fence.i
 | |
| 
 | |
|     # Test not being able to write illegal SATP mode
 | |
|     li t5, 0xA000000000080010
 | |
|     csrw satp, t5
 | |
| 
 | |
|     # Page table root address at 0x80010000; SV48
 | |
|     li t5, 0x9000000000080010
 | |
|     csrw satp, t5
 | |
| 
 | |
|     # sfence.vma x0, x0
 | |
| 
 | |
|     # switch to supervisor mode
 | |
|     li a0, 1
 | |
|     ecall
 | |
| 
 | |
|     # Instruction fetch from misaligned pages
 | |
|     jal changetoipfhandler  # set up trap handler to return from instruction page fault if necessary
 | |
|     li t0, 0x8000000000
 | |
|     jalr ra, t0 # jump misaligned terapage
 | |
|     li t0, 0x00000000
 | |
|     jalr ra, t0 # jump to misaligned gigapage
 | |
|     li t0, 0x80200000
 | |
|     jalr ra, t0 # jump to misaligned megapage
 | |
|     li t0, 0x7FFFFFFF80000000
 | |
| 
 | |
| 
 | |
|     jalr ra, t0 # jump to page with UpperBitsUnequal
 | |
|     li t0, 0x0000000080C00000
 | |
|     jalr ra, t0 # jump to page with bad reserved bits 60:54 in PTE
 | |
| 
 | |
|     # test with ENVCFG_ADUE = 1: switch to machine mode, set ADUE, access page with A=0, clear ADUE,
 | |
|     li a0, 3
 | |
|     ecall       # switch to machine mode
 | |
|     li t0, 1
 | |
|     slli t0, t0, 61
 | |
|     csrs menvcfg, t0 # set menvcfg.ADUE
 | |
|     li a0, 1
 | |
|     ecall       # switch back to supervisor mode
 | |
|     li t0, 0x0000000080E00000
 | |
|     jalr ra, t0 # jump to page without accessed bit yet set
 | |
|     li a0, 3
 | |
|     ecall       # switch to machine mode
 | |
|     li t0, 1
 | |
|     slli t0, t0, 61
 | |
|     csrc menvcfg, t0 # clear menvcfg.ADUE
 | |
|     li a0, 1
 | |
|     ecall       # switch back to supervisor mode
 | |
| 
 | |
|      # exercise malformed PBMT pages
 | |
| 
 | |
|     # page has PBMT = 3 (reserved)
 | |
|     li t0, 0x80400000
 | |
|     lw t1, 0(t0)    # read from page
 | |
|     sw t1, 0(t0)    # write to page
 | |
|     jalr ra, t0     # jump to page
 | |
| 
 | |
|     # AMO at page has PBMT = 2 or 1 (uncached)
 | |
|     li t0, 0x80401000
 | |
|     li t1, 10
 | |
|     amoadd.w t1, t1, (t0)
 | |
| 
 | |
|     la t2, SpecialPage
 | |
|     li t0, 0x200000000  # an address to a specific 1 GiB page
 | |
|     j ConcurrentICacheMissDTLBMiss
 | |
| 
 | |
| .align 6
 | |
| ConcurrentICacheMissDTLBMiss:
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|         nop
 | |
|     lw t1, 0(t0)
 | |
| 
 | |
|     # write a cacheline length (512 bits) to memory in uncached region
 | |
|     li t0, 0x80401000
 | |
|     cbo.zero (t0)
 | |
| 
 | |
|     # Nonleaf PTE has PBMT != 0     causes a page fault during page walking.  H
 | |
|     li t0, 0x80600000
 | |
|     lw t1, 0(t0)    # read from page
 | |
|     sw t1, 0(t0)    # write to page
 | |
|     jalr ra, t0     # jump to page
 | |
| 
 | |
|     # jump to address for TLB miss to trigger HPTW to make access with DisableTranslation = 1, Translate = 0
 | |
|     li t0, 0x80805000
 | |
|     jalr ra, t0
 | |
|     li t0, 0x80807000 # again, triggering setting access bit
 | |
|     jalr ra, t0
 | |
| 
 | |
|     # atomic access to uncachable memory
 | |
|     #li t0, 0x80806000
 | |
|     #sd zero, 0(t0)
 | |
|     #amoadd.w t1, t0, (t0)
 | |
| 
 | |
|     # Good PBMT with menvcfg.PBMTE = 0
 | |
|     li a0, 3
 | |
|     ecall   # switch to machine mode
 | |
|     li t5, 0x1
 | |
|     slli t5, t5, 62
 | |
|     csrc menvcfg, t5  # menvcfg.PBMTE = 0
 | |
|     li a0, 1
 | |
|     ecall   # switch back to supervisor mode
 | |
|     li t0, 0x80806000
 | |
|     jalr ra, t0      # jump to page to exercise ITLB with PBMT !=0 when ENVCFG_PMTE=0
 | |
| 
 | |
|     # Load and AMO operation on page table entry that causes access fault
 | |
|     li t0, 0x81000000
 | |
|     lw t1, 0(t0)
 | |
|     sfence.vma
 | |
|     amoadd.w t0, t0, 0(t0)
 | |
| 
 | |
|     # Access fault on top level PTE
 | |
|     li t0, 0x1000000000
 | |
|     lw t1, 0(t0)
 | |
| 
 | |
|     # Bad PBMT on top level PTE
 | |
|     li t0, 0x1800000000
 | |
|     lw t1, 0(t0)
 | |
| 
 | |
|     # Access fault on megapage
 | |
|     li t0, 0x81400000
 | |
|     lw t1, 0(t0)
 | |
| 
 | |
|     # Access fault walking page tables at megapage level
 | |
|     li t0, 0xC0000000
 | |
|     lw t1, 0(t0)
 | |
| 
 | |
|     # AMO operation on page table entry that causes page fault due to malformed PBMT
 | |
|     li t0, 0x81200000
 | |
|     jalr t0          # Attempt to fetch instruction from address causing faulty page walk
 | |
|     lw t1, 0(t0)
 | |
|     sfence.vma
 | |
|     amoadd.w t0, t0, 0(t0)
 | |
| 
 | |
|     # point top-level page table to an illegal address and verify it faults
 | |
|     li t0, 0x9000000000070000 # trap handler at non-existing memory location
 | |
|     csrw satp, t0 # should cause trap
 | |
|     sfence.vma
 | |
|     nop
 | |
| 
 | |
| 
 | |
|     # change back to default trap handler after checking everything that might cause an instruction page fault
 | |
|     jal changetodefaulthandler
 | |
| 
 | |
|     # uncachable AMO access
 | |
|     li t0, 0x80401000  # PBMT sets as uncachable
 | |
|     amoadd.w t0, t0, 0(t0)
 | |
| 
 | |
|     # exercise CBOM instructions with various permissions
 | |
|     li t0, 0x80800000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80801000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80802000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80803000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80804000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
| 
 | |
|     # set mstatus.MXR
 | |
|     li a0, 3
 | |
|     ecall
 | |
|     li t0, 1
 | |
|     slli t0, t0, 19
 | |
|     csrs mstatus, t0 # mstatus.mxr = 1
 | |
|     li a0, 1
 | |
|     ecall
 | |
| 
 | |
|     # exercise CBOM again now that MXR is set
 | |
|     li t0, 0x80800000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80801000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80802000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80803000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
|     li t0, 0x80804000
 | |
|     cbo.zero (t0)
 | |
|     cbo.clean (t0)
 | |
| 
 | |
|     # clear mstatus.MXR
 | |
|     li a0, 3
 | |
|     ecall
 | |
|     li t0, 1
 | |
|     slli t0, t0, 19
 | |
|     csrc mstatus, t0 # mstatus.mxr = 1
 | |
|     li a0, 1
 | |
|     ecall
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|     # wrap up
 | |
|     li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry
 | |
|     ecall
 | |
|     j done
 | |
| 
 | |
| backandforth:
 | |
|     ret
 | |
| 
 | |
| changetoipfhandler:
 | |
|     li a0, 3
 | |
|     ecall       # switch to machine mode
 | |
|     la a0, ipf_handler
 | |
|     csrw mtvec, a0 # point to new handler
 | |
|     li a0, 1
 | |
|     ecall       # switch back to supervisor mode
 | |
|     ret
 | |
| 
 | |
| changetodefaulthandler:
 | |
|     li a0, 3
 | |
|     ecall       # switch to machine mode
 | |
|     la a0, trap_handler
 | |
|     csrw mtvec, a0 # point to new handler
 | |
|     li a0, 1
 | |
|     ecall       # switch back to supervisor mode
 | |
|     ret
 | |
| 
 | |
| instructionpagefaulthandler:
 | |
|     csrw mepc, ra # go back to calling function
 | |
|     mret
 | |
| 
 | |
| .align 4                # trap handlers must be aligned to multiple of 16
 | |
| ipf_handler:
 | |
|     # Load trap handler stack pointer tp
 | |
|     csrrw tp, mscratch, tp  # swap MSCRATCH and tp
 | |
|     sd t0, 0(tp)        # Save t0 and t1 on the stack
 | |
|     sd t1, -8(tp)
 | |
|     li t5, 0x9000000000080010
 | |
|     csrw satp, t5       # make sure we are pointing to the root page table
 | |
|     csrr t0, mcause     # Check the cause
 | |
|     li t1, 8            # is it an ecall trap?
 | |
|     andi t0, t0, 0xFC   # if CAUSE = 8, 9, or 11
 | |
|     beq t0, t1, ecall   # yes, take ecall
 | |
|     csrr t0, mcause
 | |
|     li t1, 12           # is it an instruction page fault
 | |
|     beq t0, t1, ipf     # yes, return to calling function
 | |
|     j trap_return
 | |
| 
 | |
| ipf:
 | |
|     csrw mepc, ra       # return to calling function
 | |
|     ld t1, -8(tp)       # restore t1 and t0
 | |
|     ld t0, 0(tp)
 | |
|     csrrw tp, mscratch, tp  # restore tp
 | |
|     mret                # return from trap
 | |
| 
 | |
| .align 4                # trap handlers must be aligned to multiple of 16
 | |
| fixsatptraphandler:
 | |
|     li t5, 0x9000000000080010   # fix satp entry to normal page table root
 | |
|     csrw satp, t5
 | |
|     mret
 | |
| 
 | |
| .data
 | |
| 
 | |
| .align 16
 | |
| # root Page table situated at 0x80010000
 | |
| pagetable:
 | |
|     .8byte 0x200044C1  # VA 0x00000000-0x7F_FFFFFFFF: PTE at 0x80011000 C1 dirty, accessed, valid
 | |
|     .8byte 0x00000000000010CF # misaligned terapage at 0x80_00000000
 | |
|     .8byte 0x00000000000000CF # access fault terapage at 0x100_00000000
 | |
|     .8byte 0x40000000200044C1 # Bad PBMT at VA 0x180_0000000
 | |
| 
 | |
| # next page table at 0x80011000
 | |
| .align 12
 | |
|     .8byte 0x00000000000010CF # misaligned gigapage at 0x00000000
 | |
|     .8byte 0x00000000200058C1 # PTE for pages at 0x40000000 pointing to 0x80150000
 | |
|     .8byte 0x00000000200048C1 # gigapage at 0x80000000 pointing to 0x80120000
 | |
|     .8byte 0x00000000000000C1 # gigapage at VA 0xC0000000 causes access fault
 | |
|     .8byte 0x0
 | |
|     .8byte 0x0
 | |
|     .8byte 0x0
 | |
|     .8byte 0x0
 | |
| SpecialPage:
 | |
|     .8byte 0x00000000200000CF   # 0x2_0000_0000 1GiB page1
 | |
| 
 | |
| 
 | |
| # Next page table at 0x80012000 for gigapage at 0x80000000
 | |
| .align 12
 | |
|     .8byte 0x0000000020004CC1  # for VA starting at 80000000 (pointer to NAPOT 64 KiB pages Page table at 80013000)
 | |
|     .8byte 0x0000000020014CCF  # for VA starting at 80200000 (misaligned megapage)
 | |
|     .8byte 0x00000000200050C1  # for VA starting at 80400000 (bad PBMT pages page table at 0x80014000)
 | |
|     .8byte 0x4000000020004CC1  # for VA starting at 80600000 (bad entry: nonleaf PTE can't have PBMT != 0)
 | |
|     .8byte 0x00000000200054C1  # for VA starting at 80800000 (testing rwx permissiosn with cbom/cboz . page table at 0x80015000)
 | |
|     .8byte 0x0000000020004CC1  # for VA starting at 80A00000 (pointer to NAPOT 64 KiB pages like at 80000000.  page table at 0x80013000)
 | |
|     .8byte 0x0F00000020004CCF  # for VA starting at 80C00000 (bad reserved field in bits 60:54)
 | |
|     .8byte 0x000000002000000F  # for VA starting at 80E00000 (megapage not dirty or accessed)
 | |
|     .8byte 0x0000000000004CC1  # for VA starting at 81000000 (nonleaf pointing to unimplemented memory causes access fault)
 | |
|     .8byte 0x4000000020004CC1  # for VA starting at 81200000 (nonleaf with PBMT nonzero causes page fault)
 | |
|     .8byte 0x00000000000000CF  # for VA starting at 81400000 (megapage with access fault)
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
|     .8byte 0x0000000020004CC1
 | |
| 
 | |
| # Leaf page table at 0x80013000 with 64 KiB NAPOT pages
 | |
| .align 12
 | |
|     #80000000
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
| 
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
| 
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
| 
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
|     .8byte 0xA0000000200020CF
 | |
| 
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
| 
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
| 
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
| 
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
|     .8byte 0x80000000200060CF
 | |
| 
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
| 
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
| 
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
| 
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
|     .8byte 0x800000002000A0CF
 | |
| 
 | |
|     .8byte 0x800000002000E0CF
 | |
|     .8byte 0x800000002000E0CF
 | |
|     .8byte 0x800000002000E0CF
 | |
|     .8byte 0x800000002000E0CF
 | |
| 
 | |
|     .8byte 0x800000002000E0CF
 | |
|     .8byte 0x800000002000E0CF
 | |
| 
 | |
| # Leaf page table at 0x80014000 with PBMT pages
 | |
| .align 12
 | |
|     #80400000
 | |
|     .8byte 0x60000000200020CF   # reserved entry             VA 80400000
 | |
|     .8byte 0x40000000201000CF   # non-cache non-idempotent   VA 80401000
 | |
| 
 | |
| # Leaf page table at 0x80015000 with various permissions for testing CBOM and CBOZ
 | |
| .align 12
 | |
|     #80800000
 | |
|     .8byte 0x00000000200000CF   # valid rwx for VA 80800000
 | |
|     .8byte 0x00000000200000CB   # valid r x for VA 80801000
 | |
|     .8byte 0x00000000200000C3   # valid r   for VA 80802000
 | |
|     .8byte 0x00000000200000C9   # valid   x for VA 80803000
 | |
|     .8byte 0x00000000200000CD   # valid  wx for VA 80804000 (illegal combination, but used to test tlbcontrol)
 | |
|     .8byte 0x00000000200000CF   # valid rwx for VA 80805000  for covering ITLB translate
 | |
|     .8byte 0x20000000200000CF   # PBMT=1    for VA 80806000  for covering ITLB BadPBMT
 | |
|     .8byte 0x000000002000000F   # valid rwx for VA 80807000  for covering UpdateDA
 |