LCOV - code coverage report
Current view: top level - arch/x86/include/asm - pgtable_64.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 27 36 75.0 %
Date: 2022-03-28 13:20:08 Functions: 2 2 100.0 %
Branches: 15 30 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _ASM_X86_PGTABLE_64_H
       3                 :            : #define _ASM_X86_PGTABLE_64_H
       4                 :            : 
       5                 :            : #include <linux/const.h>
       6                 :            : #include <asm/pgtable_64_types.h>
       7                 :            : 
       8                 :            : #ifndef __ASSEMBLY__
       9                 :            : 
      10                 :            : /*
      11                 :            :  * This file contains the functions and defines necessary to modify and use
      12                 :            :  * the x86-64 page table tree.
      13                 :            :  */
      14                 :            : #include <asm/processor.h>
      15                 :            : #include <linux/bitops.h>
      16                 :            : #include <linux/threads.h>
      17                 :            : #include <asm/fixmap.h>
      18                 :            : 
      19                 :            : extern p4d_t level4_kernel_pgt[512];
      20                 :            : extern p4d_t level4_ident_pgt[512];
      21                 :            : extern pud_t level3_kernel_pgt[512];
      22                 :            : extern pud_t level3_ident_pgt[512];
      23                 :            : extern pmd_t level2_kernel_pgt[512];
      24                 :            : extern pmd_t level2_fixmap_pgt[512];
      25                 :            : extern pmd_t level2_ident_pgt[512];
      26                 :            : extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM];
      27                 :            : extern pgd_t init_top_pgt[];
      28                 :            : 
      29                 :            : #define swapper_pg_dir init_top_pgt
      30                 :            : 
      31                 :            : extern void paging_init(void);
      32                 :         90 : static inline void sync_initial_page_table(void) { }
      33                 :            : 
      34                 :            : #define pte_ERROR(e)                                    \
      35                 :            :         pr_err("%s:%d: bad pte %p(%016lx)\n",         \
      36                 :            :                __FILE__, __LINE__, &(e), pte_val(e))
      37                 :            : #define pmd_ERROR(e)                                    \
      38                 :            :         pr_err("%s:%d: bad pmd %p(%016lx)\n",         \
      39                 :            :                __FILE__, __LINE__, &(e), pmd_val(e))
      40                 :            : #define pud_ERROR(e)                                    \
      41                 :            :         pr_err("%s:%d: bad pud %p(%016lx)\n",         \
      42                 :            :                __FILE__, __LINE__, &(e), pud_val(e))
      43                 :            : 
      44                 :            : #if CONFIG_PGTABLE_LEVELS >= 5
      45                 :            : #define p4d_ERROR(e)                                    \
      46                 :            :         pr_err("%s:%d: bad p4d %p(%016lx)\n",         \
      47                 :            :                __FILE__, __LINE__, &(e), p4d_val(e))
      48                 :            : #endif
      49                 :            : 
      50                 :            : #define pgd_ERROR(e)                                    \
      51                 :            :         pr_err("%s:%d: bad pgd %p(%016lx)\n",         \
      52                 :            :                __FILE__, __LINE__, &(e), pgd_val(e))
      53                 :            : 
      54                 :            : struct mm_struct;
      55                 :            : 
      56                 :            : void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t new_pte);
      57                 :            : void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte);
      58                 :            : 
      59                 :   43022793 : static inline void native_set_pte(pte_t *ptep, pte_t pte)
      60                 :            : {
      61   [ +  +  +  +  :   42446640 :         WRITE_ONCE(*ptep, pte);
                   -  - ]
      62                 :            : }
      63                 :            : 
      64                 :   19084985 : static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
      65                 :            :                                     pte_t *ptep)
      66                 :            : {
      67         [ -  + ]:   19084985 :         native_set_pte(ptep, native_make_pte(0));
      68                 :     679050 : }
      69                 :            : 
      70                 :     145561 : static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
      71                 :            : {
      72                 :     145561 :         native_set_pte(ptep, pte);
      73                 :            : }
      74                 :            : 
      75                 :     831914 : static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
      76                 :            : {
      77   [ +  +  +  - ]:     831914 :         WRITE_ONCE(*pmdp, pmd);
      78                 :            : }
      79                 :            : 
      80                 :     358127 : static inline void native_pmd_clear(pmd_t *pmd)
      81                 :            : {
      82         [ #  # ]:     358127 :         native_set_pmd(pmd, native_make_pmd(0));
      83                 :          0 : }
      84                 :            : 
      85                 :    1922670 : static inline pte_t native_ptep_get_and_clear(pte_t *xp)
      86                 :            : {
      87                 :            : #ifdef CONFIG_SMP
      88         [ +  + ]:    1922670 :         return native_make_pte(xchg(&xp->pte, 0));
      89                 :            : #else
      90                 :            :         /* native_local_ptep_get_and_clear,
      91                 :            :            but duplicated because of cyclic dependency */
      92                 :            :         pte_t ret = *xp;
      93                 :            :         native_pte_clear(NULL, 0, xp);
      94                 :            :         return ret;
      95                 :            : #endif
      96                 :            : }
      97                 :            : 
      98                 :            : static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
      99                 :            : {
     100                 :            : #ifdef CONFIG_SMP
     101                 :            :         return native_make_pmd(xchg(&xp->pmd, 0));
     102                 :            : #else
     103                 :            :         /* native_local_pmdp_get_and_clear,
     104                 :            :            but duplicated because of cyclic dependency */
     105                 :            :         pmd_t ret = *xp;
     106                 :            :         native_pmd_clear(xp);
     107                 :            :         return ret;
     108                 :            : #endif
     109                 :            : }
     110                 :            : 
     111                 :     480277 : static inline void native_set_pud(pud_t *pudp, pud_t pud)
     112                 :            : {
     113   [ +  -  -  -  :     480277 :         WRITE_ONCE(*pudp, pud);
                   +  - ]
     114                 :            : }
     115                 :            : 
     116                 :     169714 : static inline void native_pud_clear(pud_t *pud)
     117                 :            : {
     118         [ #  # ]:     169714 :         native_set_pud(pud, native_make_pud(0));
     119                 :          0 : }
     120                 :            : 
     121                 :            : static inline pud_t native_pudp_get_and_clear(pud_t *xp)
     122                 :            : {
     123                 :            : #ifdef CONFIG_SMP
     124                 :            :         return native_make_pud(xchg(&xp->pud, 0));
     125                 :            : #else
     126                 :            :         /* native_local_pudp_get_and_clear,
     127                 :            :          * but duplicated because of cyclic dependency
     128                 :            :          */
     129                 :            :         pud_t ret = *xp;
     130                 :            : 
     131                 :            :         native_pud_clear(xp);
     132                 :            :         return ret;
     133                 :            : #endif
     134                 :            : }
     135                 :            : 
     136                 :     250963 : static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
     137                 :            : {
     138                 :     250963 :         pgd_t pgd;
     139                 :            : 
     140   [ -  +  -  + ]:     250963 :         if (pgtable_l5_enabled() || !IS_ENABLED(CONFIG_PAGE_TABLE_ISOLATION)) {
     141                 :          0 :                 WRITE_ONCE(*p4dp, p4d);
     142                 :          0 :                 return;
     143                 :            :         }
     144                 :            : 
     145                 :     250963 :         pgd = native_make_pgd(native_p4d_val(p4d));
     146                 :     250963 :         pgd = pti_set_user_pgtbl((pgd_t *)p4dp, pgd);
     147                 :     250963 :         WRITE_ONCE(*p4dp, native_make_p4d(native_pgd_val(pgd)));
     148                 :            : }
     149                 :            : 
     150                 :     123764 : static inline void native_p4d_clear(p4d_t *p4d)
     151                 :            : {
     152         [ -  + ]:     123764 :         native_set_p4d(p4d, native_make_p4d(0));
     153                 :        960 : }
     154                 :            : 
     155                 :          0 : static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
     156                 :            : {
     157                 :          0 :         WRITE_ONCE(*pgdp, pti_set_user_pgtbl(pgdp, pgd));
     158                 :            : }
     159                 :            : 
     160                 :          0 : static inline void native_pgd_clear(pgd_t *pgd)
     161                 :            : {
     162                 :          0 :         native_set_pgd(pgd, native_make_pgd(0));
     163                 :          0 : }
     164                 :            : 
     165                 :            : extern void sync_global_pgds(unsigned long start, unsigned long end);
     166                 :            : 
     167                 :            : /*
     168                 :            :  * Conversion functions: convert a page and protection to a page entry,
     169                 :            :  * and a page entry and page directory to the page they refer to.
     170                 :            :  */
     171                 :            : 
     172                 :            : /*
     173                 :            :  * Level 4 access.
     174                 :            :  */
     175                 :            : #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
     176                 :            : 
     177                 :            : /* PUD - Level3 access */
     178                 :            : 
     179                 :            : /* PMD  - Level 2 access */
     180                 :            : 
     181                 :            : /* PTE - Level 1 access. */
     182                 :            : 
     183                 :            : /* x86-64 always has all page tables mapped. */
     184                 :            : #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
     185                 :            : #define pte_unmap(pte) ((void)(pte))/* NOP */
     186                 :            : 
     187                 :            : /*
     188                 :            :  * Encode and de-code a swap entry
     189                 :            :  *
     190                 :            :  * |     ...            | 11| 10|  9|8|7|6|5| 4| 3|2| 1|0| <- bit number
     191                 :            :  * |     ...            |SW3|SW2|SW1|G|L|D|A|CD|WT|U| W|P| <- bit names
     192                 :            :  * | TYPE (59-63) | ~OFFSET (9-58)  |0|0|X|X| X| X|X|SD|0| <- swp entry
     193                 :            :  *
     194                 :            :  * G (8) is aliased and used as a PROT_NONE indicator for
     195                 :            :  * !present ptes.  We need to start storing swap entries above
     196                 :            :  * there.  We also need to avoid using A and D because of an
     197                 :            :  * erratum where they can be incorrectly set by hardware on
     198                 :            :  * non-present PTEs.
     199                 :            :  *
     200                 :            :  * SD (1) in swp entry is used to store soft dirty bit, which helps us
     201                 :            :  * remember soft dirty over page migration
     202                 :            :  *
     203                 :            :  * Bit 7 in swp entry should be 0 because pmd_present checks not only P,
     204                 :            :  * but also L and G.
     205                 :            :  *
     206                 :            :  * The offset is inverted by a binary not operation to make the high
     207                 :            :  * physical bits set.
     208                 :            :  */
     209                 :            : #define SWP_TYPE_BITS           5
     210                 :            : 
     211                 :            : #define SWP_OFFSET_FIRST_BIT    (_PAGE_BIT_PROTNONE + 1)
     212                 :            : 
     213                 :            : /* We always extract/encode the offset by shifting it all the way up, and then down again */
     214                 :            : #define SWP_OFFSET_SHIFT        (SWP_OFFSET_FIRST_BIT+SWP_TYPE_BITS)
     215                 :            : 
     216                 :            : #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
     217                 :            : 
     218                 :            : /* Extract the high bits for type */
     219                 :            : #define __swp_type(x) ((x).val >> (64 - SWP_TYPE_BITS))
     220                 :            : 
     221                 :            : /* Shift up (to get rid of type), then down to get value */
     222                 :            : #define __swp_offset(x) (~(x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT)
     223                 :            : 
     224                 :            : /*
     225                 :            :  * Shift the offset up "too far" by TYPE bits, then down again
     226                 :            :  * The offset is inverted by a binary not operation to make the high
     227                 :            :  * physical bits set.
     228                 :            :  */
     229                 :            : #define __swp_entry(type, offset) ((swp_entry_t) { \
     230                 :            :         (~(unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \
     231                 :            :         | ((unsigned long)(type) << (64-SWP_TYPE_BITS)) })
     232                 :            : 
     233                 :            : #define __pte_to_swp_entry(pte)         ((swp_entry_t) { pte_val((pte)) })
     234                 :            : #define __pmd_to_swp_entry(pmd)         ((swp_entry_t) { pmd_val((pmd)) })
     235                 :            : #define __swp_entry_to_pte(x)           ((pte_t) { .pte = (x).val })
     236                 :            : #define __swp_entry_to_pmd(x)           ((pmd_t) { .pmd = (x).val })
     237                 :            : 
     238                 :            : extern int kern_addr_valid(unsigned long addr);
     239                 :            : extern void cleanup_highmap(void);
     240                 :            : 
     241                 :            : #define HAVE_ARCH_UNMAPPED_AREA
     242                 :            : #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
     243                 :            : 
     244                 :            : #define PAGE_AGP    PAGE_KERNEL_NOCACHE
     245                 :            : #define HAVE_PAGE_AGP 1
     246                 :            : 
     247                 :            : /* fs/proc/kcore.c */
     248                 :            : #define kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
     249                 :            : #define kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
     250                 :            : 
     251                 :            : #define __HAVE_ARCH_PTE_SAME
     252                 :            : 
     253                 :            : #define vmemmap ((struct page *)VMEMMAP_START)
     254                 :            : 
     255                 :            : extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
     256                 :            : extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
     257                 :            : 
     258                 :            : #define gup_fast_permitted gup_fast_permitted
     259                 :            : static inline bool gup_fast_permitted(unsigned long start, unsigned long end)
     260                 :            : {
     261                 :            :         if (end >> __VIRTUAL_MASK_SHIFT)
     262                 :            :                 return false;
     263                 :            :         return true;
     264                 :            : }
     265                 :            : 
     266                 :            : #include <asm/pgtable-invert.h>
     267                 :            : 
     268                 :            : #endif /* !__ASSEMBLY__ */
     269                 :            : #endif /* _ASM_X86_PGTABLE_64_H */

Generated by: LCOV version 1.14