Introduce XenResetVector, a copy of OvmfPkg/ResetVector, with one changes: - SEC_DEFAULT_CR0: enable cache (bit 30 or CD set to 0) Xen copies the OVMF code to RAM, there is no need to disable cache. This new module will later be modified to add a new entry point, more detail in a following commit "OvmfPkg/XenResetVector: Add new entry point for Xen PVH" Value FILE_GUID of XenResetVector have not changed compare to ResetVector because it is a special value (gEfiFirmwareVolumeTopFileGuid). Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689 Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20190813113119.14804-4-anthony.perard@citrix.com>
		
			
				
	
	
		
			150 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;------------------------------------------------------------------------------
 | |
| ; @file
 | |
| ; Sets the CR3 register for 64-bit paging
 | |
| ;
 | |
| ; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
 | |
| ; Copyright (c) 2019, Citrix Systems, Inc.
 | |
| ; SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| ;
 | |
| ;------------------------------------------------------------------------------
 | |
| 
 | |
| BITS    32
 | |
| 
 | |
| %define PAGE_PRESENT            0x01
 | |
| %define PAGE_READ_WRITE         0x02
 | |
| %define PAGE_USER_SUPERVISOR    0x04
 | |
| %define PAGE_WRITE_THROUGH      0x08
 | |
| %define PAGE_CACHE_DISABLE     0x010
 | |
| %define PAGE_ACCESSED          0x020
 | |
| %define PAGE_DIRTY             0x040
 | |
| %define PAGE_PAT               0x080
 | |
| %define PAGE_GLOBAL           0x0100
 | |
| %define PAGE_2M_MBO            0x080
 | |
| %define PAGE_2M_PAT          0x01000
 | |
| 
 | |
| %define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
 | |
|                           PAGE_ACCESSED + \
 | |
|                           PAGE_DIRTY + \
 | |
|                           PAGE_READ_WRITE + \
 | |
|                           PAGE_PRESENT)
 | |
| 
 | |
| %define PAGE_PDP_ATTR (PAGE_ACCESSED + \
 | |
|                        PAGE_READ_WRITE + \
 | |
|                        PAGE_PRESENT)
 | |
| 
 | |
| ; Check if Secure Encrypted Virtualization (SEV) feature is enabled
 | |
| ;
 | |
| ; If SEV is enabled then EAX will be at least 32
 | |
| ; If SEV is disabled then EAX will be zero.
 | |
| ;
 | |
| CheckSevFeature:
 | |
|     ; Check if we have a valid (0x8000_001F) CPUID leaf
 | |
|     mov       eax, 0x80000000
 | |
|     cpuid
 | |
| 
 | |
|     ; This check should fail on Intel or Non SEV AMD CPUs. In future if
 | |
|     ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
 | |
|     ; same bit definition.
 | |
|     cmp       eax, 0x8000001f
 | |
|     jl        NoSev
 | |
| 
 | |
|     ; Check for memory encryption feature:
 | |
|     ;  CPUID  Fn8000_001F[EAX] - Bit 1
 | |
|     ;
 | |
|     mov       eax,  0x8000001f
 | |
|     cpuid
 | |
|     bt        eax, 1
 | |
|     jnc       NoSev
 | |
| 
 | |
|     ; Check if memory encryption is enabled
 | |
|     ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
 | |
|     mov       ecx, 0xc0010131
 | |
|     rdmsr
 | |
|     bt        eax, 0
 | |
|     jnc       NoSev
 | |
| 
 | |
|     ; Get pte bit position to enable memory encryption
 | |
|     ; CPUID Fn8000_001F[EBX] - Bits 5:0
 | |
|     ;
 | |
|     mov       eax, ebx
 | |
|     and       eax, 0x3f
 | |
|     jmp       SevExit
 | |
| 
 | |
| NoSev:
 | |
|     xor       eax, eax
 | |
| 
 | |
| SevExit:
 | |
|     OneTimeCallRet CheckSevFeature
 | |
| 
 | |
| ;
 | |
| ; Modified:  EAX, EBX, ECX, EDX
 | |
| ;
 | |
| SetCr3ForPageTables64:
 | |
| 
 | |
|     OneTimeCall   CheckSevFeature
 | |
|     xor     edx, edx
 | |
|     test    eax, eax
 | |
|     jz      SevNotActive
 | |
| 
 | |
|     ; If SEV is enabled, C-bit is always above 31
 | |
|     sub     eax, 32
 | |
|     bts     edx, eax
 | |
| 
 | |
| SevNotActive:
 | |
| 
 | |
|     ;
 | |
|     ; For OVMF, build some initial page tables at
 | |
|     ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
 | |
|     ;
 | |
|     ; This range should match with PcdOvmfSecPageTablesSize which is
 | |
|     ; declared in the FDF files.
 | |
|     ;
 | |
|     ; At the end of PEI, the pages tables will be rebuilt into a
 | |
|     ; more permanent location by DxeIpl.
 | |
|     ;
 | |
| 
 | |
|     mov     ecx, 6 * 0x1000 / 4
 | |
|     xor     eax, eax
 | |
| clearPageTablesMemoryLoop:
 | |
|     mov     dword[ecx * 4 + PT_ADDR (0) - 4], eax
 | |
|     loop    clearPageTablesMemoryLoop
 | |
| 
 | |
|     ;
 | |
|     ; Top level Page Directory Pointers (1 * 512GB entry)
 | |
|     ;
 | |
|     mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
 | |
|     mov     dword[PT_ADDR (4)], edx
 | |
| 
 | |
|     ;
 | |
|     ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
 | |
|     ;
 | |
|     mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
 | |
|     mov     dword[PT_ADDR (0x1004)], edx
 | |
|     mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
 | |
|     mov     dword[PT_ADDR (0x100C)], edx
 | |
|     mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
 | |
|     mov     dword[PT_ADDR (0x1014)], edx
 | |
|     mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
 | |
|     mov     dword[PT_ADDR (0x101C)], edx
 | |
| 
 | |
|     ;
 | |
|     ; Page Table Entries (2048 * 2MB entries => 4GB)
 | |
|     ;
 | |
|     mov     ecx, 0x800
 | |
| pageTableEntriesLoop:
 | |
|     mov     eax, ecx
 | |
|     dec     eax
 | |
|     shl     eax, 21
 | |
|     add     eax, PAGE_2M_PDE_ATTR
 | |
|     mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
 | |
|     mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
 | |
|     loop    pageTableEntriesLoop
 | |
| 
 | |
|     ;
 | |
|     ; Set CR3 now that the paging structures are available
 | |
|     ;
 | |
|     mov     eax, PT_ADDR (0)
 | |
|     mov     cr3, eax
 | |
| 
 | |
|     OneTimeCallRet SetCr3ForPageTables64
 |