/* IDENT X-13 */ /************************************************************************ * * * HPE CONFIDENTIAL. This software is confidential proprietary software * * licensed by Hewlett Packard Enterprise Development, LP, and is not * * authorized to be used, duplicated or disclosed to anyone without the * * prior written permission of HPE. * * Copyright 2018 Hewlett Packard Enterprise Development, LP * * * * VMS SOFTWARE, INC. CONFIDENTIAL. This software is confidential * * proprietary software licensed by VMS Software, Inc., and is not * * authorized to be used, duplicated or disclosed to anyone without * * the prior written permission of VMS Software, Inc. * * Copyright 2018 VMS Software, Inc. * * * *************************************************************************/ /* *++ * FACILITY: * * VMS Executive (LIB) * * ABSTRACT: * * This header file provides the basic set of C inline functions for * accessing PTEs. * * AUTHOR: * * Karen L. Noel * * CREATION DATE: 28-Mar-2000 * * MODIFICATION HISTORY: * * X-13 CEG0918 Clair Grant 25-Sep-2020 * Change comment in X-12 * * X-12 CEG0909 Clair Grant 24-Sep-2020 * Replace "// comment" style to eliminate * confusion when compiling /STANDARD=VAXC. * * X-11 LMN Lisa Nevin 20-Dec-2019 * verify pfns are even on x86 in write_one_pte when the pte is * valid * * X-10 GHJ Gregory H. Jordan 10-Dec-2018 * Revert hwrpb def due to conflicts. * * X-9 GHJ Gregory H. Jordan 10-Dec-2018 * Update various data cells to use __RUNCONST instead of * const. * * X-8 MJM Michael Moroney 20-Nov-2018 * Add $write_one_pte() macro for X86, writes the kernel * PTE pair only. * * X-7 GHJ Gregory H. Jordan 20-Jun-2018 * Change conditionals to use __alpha to avoid the need to * include arch_defs.h. * * X-6 GHJ Gregory H. Jordan 21-May-2018 * Add the $wrpte_pte macro back here (it had moved to VMS_MACROS) * and VMS_MACROS was including this module for Alpha. The * definitions of a number of extern symbols (mmg$gq_page_size, * mmg$gq_bwp_mask, etc... then conflicted with definitions * in other modules which were defining them as ints and not * uint64. * * X-5 GHJ Gregory H. Jordan 21-May-2018 * Change the $write_pte routine to be Alpha specific and * rename to $write_pte_alpha. VMS_MACROS.H now has a * $write_pte macro that will call this routines for Alpha * and do teh appropriate work for IA64 and X86. * * X-4 PAJ1567 Paul A. Jacobi 11-Jan-2018 * Limit reference of HWRPB$V_VIRBND to Alpha. The field * is always 0 on IA64 and does not exist on X86_64. * * X-3 KLN3025 Karen L. Noel 26-Feb-2002 * o Port PT space to IA64. * o Remove inline pragmas. We trust the compiler now. * * X-2 KLN2200 Karen L. Noel 15-Nov-2000 * Fix nested comments. *-- */ /* Include any header files we need to make these functions work */ #ifndef __PTE_FUNCTIONS_LOADED #define __PTE_FUNCTIONS_LOADED 1 /* This construct allows SYSBOOT write access to variables that are run-time constants, but need to be initialized at boot time. */ #ifdef __SYSBOOT #define __RUNCONST #else #define __RUNCONST const #endif #ifdef __INITIAL_POINTER_SIZE /* Defined whenever ptr size pragmas supported */ #pragma __required_pointer_size __save /* Save the previously-defined required ptr size */ #pragma __required_pointer_size __short /* And set ptr size default to 32-bit pointers */ #endif #include #include #include #include #include #include /* *++ * $read_pte - Read a PTE * * This function reads a PTE. * * With VIRBND and SYSPTBR enabled, the level 1 page table page cannot be referenced * safely in a virtual manner. This function references the level 1 page table * physically when necessary. * * Input: pte_address - Address of PTE to read * Output: contents_p - Address to store the contents of the PTE *-- */ static void $read_pte (PTE_PQ pte_address, PTE_PQ contents_p) { extern PTE mmg$read_l1pte (PTE_PQ pte_address); extern PTE_PQ __RUNCONST mmg$gq_l1_base[VA$C_VRNX_COUNT]; extern uint64 __RUNCONST mmg$gq_page_size; extern uint64 __RUNCONST mmg$gq_bwp_width; extern uint64 __RUNCONST mmg$gq_bwp_mask; extern HWRPB * exe$gpq_hwrpb; /* If this system doesn't support system space page tables */ /* or, if this isn't a L1 PTE address, just read the PTE */ /* Note for IA64, hwprb$v_virbnd == 0. The field does not */ /* exist on X86_64. This make the following test always */ /* TRUE on IA64 and X86_64. */ #if defined (__alpha) /* Verified for x86 port - Gregory H. Jordan */ if ((exe$gpq_hwrpb->hwrpb$v_virbnd == 0) || ((uint64)pte_address < (uint64)mmg$gq_l1_base[VA$C_VRNX_SYSTEM]) || ((uint64)pte_address >= (uint64)mmg$gq_l1_base[VA$C_VRNX_SYSTEM]+mmg$gq_page_size)) #else if (1) #endif { *contents_p = *pte_address; return; } /* Call a macro-32 routine to read the L1PTE physically */ *contents_p = mmg$read_l1pte(pte_address); return; } /* $write_pte() macro - use to write a PTE into the page tables * * For X86, use the global routine mmg$write_pte_x86 in mmg_routines.c. * For IA64, just write the PTE into the provide address. * For Alpha, use $write_pte_alpha defined in pte_functions.h */ #if defined(__x86_64) #define $write_pte( vapte, pte ) mmg$write_pte_x86( vapte, pte ) #elif defined (__ia64) /* Verified for x86 port - Gregory H. Jordan */ #define $write_pte( vapte, pte) *vapte = pte #elif defined (__alpha) /* Verified for x86 port - Gregory H. Jordan */ #define $write_pte( vapte, pte) $write_pte_alpha(vapte, pte) #else #error Need architecture specific work here #endif /*+++ * $write_pte_alpha - Write to a PTE (Alpha) * * This function writes to a PTE on Alpha. The routine is called by the $write_pte macro * defined in VMS_MACROS.H. * * With VIRBND and SYSPTBR enabled, the level 1 page table page cannot be referenced * safely in a virtual manner. This function references the level 1 page table * physically when necessary. * * Input: pte_address - Address of PTE to write * contents - The contents to write to the PTE * *--- */ #if defined (__alpha) /* Verified for x86 port - Gregory H. Jordan */ static void $write_pte_alpha (PTE_PQ pte_address, PTE contents) { extern uint64 mmg$write_l1pte (PTE_PQ pte_address, PTE contents); extern PTE_PQ __RUNCONST mmg$gq_l1_base[VA$C_VRNX_COUNT]; extern uint64 __RUNCONST mmg$gq_page_size; extern uint64 __RUNCONST mmg$gq_bwp_width; extern uint64 __RUNCONST mmg$gq_bwp_mask; extern HWRPB * exe$gpq_hwrpb; /* If this system doesn't support system space page tables */ /* or, if this isn't a L1 PTE address, just write the PTE */ /* Note for IA64, hwprb$v_virbnd == 0. The field does not */ /* exist on X86_64. This make the following test always */ /* TRUE on IA64 and X86_64. */ if ((exe$gpq_hwrpb->hwrpb$v_virbnd == 0) || ((uint64)pte_address < (uint64)mmg$gq_l1_base[VA$C_VRNX_SYSTEM]) || ((uint64)pte_address >= (uint64)mmg$gq_l1_base[VA$C_VRNX_SYSTEM]+mmg$gq_page_size)) { *pte_address = contents; return; } /* Call a macro-32 routine to write the L1PTE physically */ mmg$write_l1pte(pte_address,contents); return; } #endif /* $write_one_pte() macro - use to write single PTE into kernel page table * * For X86, write the single PTE pair, incrementing PFN if valid. * For IA64 and Alpha, this is identical to $write_pte. */ #if defined(__x86_64) /* Verified for x86 port - Michael Moroney */ #define $write_one_pte( vapte, pte ) { \ PTE pte2 = (pte); \ PTE_PQ va2 = (vapte); \ if (pte2.pte$v_valid) { \ if (pte2.pte$v_pfn_4k & 1ull) { \ uint64 ra = __RETURN_ADDRESS(); \ exe$kprintf("\n Expected an even PFN but received odd PFN: %08X.%08X RA: %08X.%08X \n", pte2.pte$v_pfn_4k >> 32, pte2.pte$v_pfn_4k & 0XFFFFFFFF, ra >> 32, ra & 0xFFFFFFFF); \ bug_check(INCONMMGST, FATAL, COLD); \ } \ *va2++ = pte2; \ pte2.pte$v_pfn_4k++; \ } \ else { \ *va2++ = pte2; \ } \ *va2 = pte2; \ } #elif defined (__ia64) /* Verified for x86 port - Gregory H. Jordan */ #define $write_one_pte( vapte, pte) *vapte = pte #elif defined (__alpha) /* Verified for x86 port - Gregory H. Jordan */ #define $write_one_pte( vapte, pte) $write_pte_alpha(vapte, pte) #else #error Need architecture specific work here #endif #ifdef __INITIAL_POINTER_SIZE /* Defined whenever ptr size pragmas supported */ #pragma __required_pointer_size __restore /* Restore the previously-defined required ptr size */ #endif #endif /* __PTE_FUNCTIONS_LOADED */