LCOV - code coverage report
Current view: top level - arch/x86/include/asm - desc.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 64 132 48.5 %
Date: 2022-04-01 14:35:51 Functions: 3 5 60.0 %
Branches: 7 44 15.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _ASM_X86_DESC_H
       3                 :            : #define _ASM_X86_DESC_H
       4                 :            : 
       5                 :            : #include <asm/desc_defs.h>
       6                 :            : #include <asm/ldt.h>
       7                 :            : #include <asm/mmu.h>
       8                 :            : #include <asm/fixmap.h>
       9                 :            : #include <asm/irq_vectors.h>
      10                 :            : #include <asm/cpu_entry_area.h>
      11                 :            : 
      12                 :            : #include <linux/smp.h>
      13                 :            : #include <linux/percpu.h>
      14                 :            : 
      15                 :          0 : static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info)
      16                 :            : {
      17                 :          0 :         desc->limit0         = info->limit & 0x0ffff;
      18                 :            : 
      19                 :          0 :         desc->base0          = (info->base_addr & 0x0000ffff);
      20                 :          0 :         desc->base1          = (info->base_addr & 0x00ff0000) >> 16;
      21                 :            : 
      22                 :          0 :         desc->type           = (info->read_exec_only ^ 1) << 1;
      23                 :          0 :         desc->type          |= info->contents << 2;
      24                 :            :         /* Set the ACCESS bit so it can be mapped RO */
      25                 :          0 :         desc->type          |= 1;
      26                 :            : 
      27                 :          0 :         desc->s                      = 1;
      28                 :          0 :         desc->dpl            = 0x3;
      29                 :          0 :         desc->p                      = info->seg_not_present ^ 1;
      30                 :          0 :         desc->limit1         = (info->limit & 0xf0000) >> 16;
      31                 :          0 :         desc->avl            = info->useable;
      32                 :          0 :         desc->d                      = info->seg_32bit;
      33                 :          0 :         desc->g                      = info->limit_in_pages;
      34                 :            : 
      35                 :          0 :         desc->base2          = (info->base_addr & 0xff000000) >> 24;
      36                 :            :         /*
      37                 :            :          * Don't allow setting of the lm bit. It would confuse
      38                 :            :          * user_64bit_mode and would get overridden by sysret anyway.
      39                 :            :          */
      40                 :          0 :         desc->l                      = 0;
      41                 :          0 : }
      42                 :            : 
      43                 :            : extern struct desc_ptr idt_descr;
      44                 :            : extern gate_desc idt_table[];
      45                 :            : extern const struct desc_ptr debug_idt_descr;
      46                 :            : extern gate_desc debug_idt_table[];
      47                 :            : 
      48                 :            : struct gdt_page {
      49                 :            :         struct desc_struct gdt[GDT_ENTRIES];
      50                 :            : } __attribute__((aligned(PAGE_SIZE)));
      51                 :            : 
      52                 :            : DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
      53                 :            : 
      54                 :            : /* Provide the original GDT */
      55                 :     610960 : static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu)
      56                 :            : {
      57                 :     610918 :         return per_cpu(gdt_page, cpu).gdt;
      58                 :            : }
      59                 :            : 
      60                 :            : /* Provide the current original GDT */
      61                 :          0 : static inline struct desc_struct *get_current_gdt_rw(void)
      62                 :            : {
      63                 :          0 :         return this_cpu_ptr(&gdt_page)->gdt;
      64                 :            : }
      65                 :            : 
      66                 :            : /* Provide the fixmap address of the remapped GDT */
      67                 :         42 : static inline struct desc_struct *get_cpu_gdt_ro(int cpu)
      68                 :            : {
      69                 :         21 :         return (struct desc_struct *)&get_cpu_entry_area(cpu)->gdt;
      70                 :            : }
      71                 :            : 
      72                 :            : /* Provide the current read-only GDT */
      73                 :            : static inline struct desc_struct *get_current_gdt_ro(void)
      74                 :            : {
      75                 :            :         return get_cpu_gdt_ro(smp_processor_id());
      76                 :            : }
      77                 :            : 
      78                 :            : /* Provide the physical address of the GDT page. */
      79                 :         21 : static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu)
      80                 :            : {
      81                 :         21 :         return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu));
      82                 :            : }
      83                 :            : 
      84                 :            : static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
      85                 :            :                              unsigned dpl, unsigned ist, unsigned seg)
      86                 :            : {
      87                 :            :         gate->offset_low     = (u16) func;
      88                 :            :         gate->bits.p         = 1;
      89                 :            :         gate->bits.dpl               = dpl;
      90                 :            :         gate->bits.zero              = 0;
      91                 :            :         gate->bits.type              = type;
      92                 :            :         gate->offset_middle  = (u16) (func >> 16);
      93                 :            : #ifdef CONFIG_X86_64
      94                 :            :         gate->segment                = __KERNEL_CS;
      95                 :            :         gate->bits.ist               = ist;
      96                 :            :         gate->reserved               = 0;
      97                 :            :         gate->offset_high    = (u32) (func >> 32);
      98                 :            : #else
      99                 :            :         gate->segment                = seg;
     100                 :            :         gate->bits.ist               = 0;
     101                 :            : #endif
     102                 :            : }
     103                 :            : 
     104                 :          0 : static inline int desc_empty(const void *ptr)
     105                 :            : {
     106                 :          0 :         const u32 *desc = ptr;
     107                 :            : 
     108   [ #  #  #  # ]:          0 :         return !(desc[0] | desc[1]);
     109                 :            : }
     110                 :            : 
     111                 :            : #ifdef CONFIG_PARAVIRT_XXL
     112                 :            : #include <asm/paravirt.h>
     113                 :            : #else
     114                 :            : #define load_TR_desc()                          native_load_tr_desc()
     115                 :            : #define load_gdt(dtr)                           native_load_gdt(dtr)
     116                 :            : #define load_idt(dtr)                           native_load_idt(dtr)
     117                 :            : #define load_tr(tr)                             asm volatile("ltr %0"::"m" (tr))
     118                 :            : #define load_ldt(ldt)                           asm volatile("lldt %0"::"m" (ldt))
     119                 :            : 
     120                 :            : #define store_gdt(dtr)                          native_store_gdt(dtr)
     121                 :            : #define store_tr(tr)                            (tr = native_store_tr())
     122                 :            : 
     123                 :            : #define load_TLS(t, cpu)                        native_load_tls(t, cpu)
     124                 :            : #define set_ldt                                 native_set_ldt
     125                 :            : 
     126                 :            : #define write_ldt_entry(dt, entry, desc)        native_write_ldt_entry(dt, entry, desc)
     127                 :            : #define write_gdt_entry(dt, entry, desc, type)  native_write_gdt_entry(dt, entry, desc, type)
     128                 :            : #define write_idt_entry(dt, entry, g)           native_write_idt_entry(dt, entry, g)
     129                 :            : 
     130                 :          0 : static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
     131                 :            : {
     132         [ #  # ]:          0 : }
     133                 :            : 
     134                 :          0 : static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
     135                 :            : {
     136         [ #  # ]:          0 : }
     137                 :            : #endif  /* CONFIG_PARAVIRT_XXL */
     138                 :            : 
     139                 :            : #define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
     140                 :            : 
     141                 :       5943 : static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate)
     142                 :            : {
     143         [ +  + ]:       5943 :         memcpy(&idt[entry], gate, sizeof(*gate));
     144                 :            : }
     145                 :            : 
     146                 :            : static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry, const void *desc)
     147                 :            : {
     148                 :            :         memcpy(&ldt[entry], desc, 8);
     149                 :            : }
     150                 :            : 
     151                 :            : static inline void
     152                 :         42 : native_write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc, int type)
     153                 :            : {
     154                 :         42 :         unsigned int size;
     155                 :            : 
     156                 :         42 :         switch (type) {
     157                 :            :         case DESC_TSS:  size = sizeof(tss_desc);        break;
     158                 :            :         case DESC_LDT:  size = sizeof(ldt_desc);        break;
     159                 :         21 :         default:        size = sizeof(*gdt);            break;
     160                 :            :         }
     161                 :            : 
     162                 :         42 :         memcpy(&gdt[entry], desc, size);
     163                 :            : }
     164                 :            : 
     165                 :         21 : static inline void set_tssldt_descriptor(void *d, unsigned long addr,
     166                 :            :                                          unsigned type, unsigned size)
     167                 :            : {
     168                 :         21 :         struct ldttss_desc *desc = d;
     169                 :            : 
     170                 :         21 :         memset(desc, 0, sizeof(*desc));
     171                 :            : 
     172                 :         21 :         desc->limit0         = (u16) size;
     173                 :         21 :         desc->base0          = (u16) addr;
     174                 :         21 :         desc->base1          = (addr >> 16) & 0xFF;
     175                 :         21 :         desc->type           = type;
     176                 :         21 :         desc->p                      = 1;
     177                 :         21 :         desc->limit1         = (size >> 16) & 0xF;
     178                 :         21 :         desc->base2          = (addr >> 24) & 0xFF;
     179                 :            : #ifdef CONFIG_X86_64
     180                 :         21 :         desc->base3          = (u32) (addr >> 32);
     181                 :            : #endif
     182                 :            : }
     183                 :            : 
     184                 :         21 : static inline void __set_tss_desc(unsigned cpu, unsigned int entry, struct x86_hw_tss *addr)
     185                 :            : {
     186                 :         21 :         struct desc_struct *d = get_cpu_gdt_rw(cpu);
     187                 :         21 :         tss_desc tss;
     188                 :            : 
     189                 :         21 :         set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
     190                 :            :                               __KERNEL_TSS_LIMIT);
     191                 :         21 :         write_gdt_entry(d, entry, &tss, DESC_TSS);
     192                 :         21 : }
     193                 :            : 
     194                 :            : #define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
     195                 :            : 
     196                 :         21 : static inline void native_set_ldt(const void *addr, unsigned int entries)
     197                 :            : {
     198         [ +  - ]:         21 :         if (likely(entries == 0))
     199                 :         21 :                 asm volatile("lldt %w0"::"q" (0));
     200                 :            :         else {
     201                 :          0 :                 unsigned cpu = smp_processor_id();
     202                 :          0 :                 ldt_desc ldt;
     203                 :            : 
     204                 :          0 :                 set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,
     205                 :          0 :                                       entries * LDT_ENTRY_SIZE - 1);
     206                 :          0 :                 write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_LDT,
     207                 :            :                                 &ldt, DESC_LDT);
     208                 :          0 :                 asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
     209                 :            :         }
     210                 :         21 : }
     211                 :            : 
     212                 :         84 : static inline void native_load_gdt(const struct desc_ptr *dtr)
     213                 :            : {
     214                 :         84 :         asm volatile("lgdt %0"::"m" (*dtr));
     215                 :            : }
     216                 :            : 
     217                 :         63 : static inline void native_load_idt(const struct desc_ptr *dtr)
     218                 :            : {
     219                 :         63 :         asm volatile("lidt %0"::"m" (*dtr));
     220                 :         21 : }
     221                 :            : 
     222                 :         21 : static inline void native_store_gdt(struct desc_ptr *dtr)
     223                 :            : {
     224                 :         21 :         asm volatile("sgdt %0":"=m" (*dtr));
     225                 :            : }
     226                 :            : 
     227                 :          0 : static inline void store_idt(struct desc_ptr *dtr)
     228                 :            : {
     229                 :          0 :         asm volatile("sidt %0":"=m" (*dtr));
     230                 :            : }
     231                 :            : 
     232                 :            : /*
     233                 :            :  * The LTR instruction marks the TSS GDT entry as busy. On 64-bit, the GDT is
     234                 :            :  * a read-only remapping. To prevent a page fault, the GDT is switched to the
     235                 :            :  * original writeable version when needed.
     236                 :            :  */
     237                 :            : #ifdef CONFIG_X86_64
     238                 :         21 : static inline void native_load_tr_desc(void)
     239                 :            : {
     240                 :         21 :         struct desc_ptr gdt;
     241                 :         21 :         int cpu = raw_smp_processor_id();
     242                 :         21 :         bool restore = 0;
     243                 :         21 :         struct desc_struct *fixmap_gdt;
     244                 :            : 
     245                 :         21 :         native_store_gdt(&gdt);
     246                 :         21 :         fixmap_gdt = get_cpu_gdt_ro(cpu);
     247                 :            : 
     248                 :            :         /*
     249                 :            :          * If the current GDT is the read-only fixmap, swap to the original
     250                 :            :          * writeable version. Swap back at the end.
     251                 :            :          */
     252         [ +  - ]:         21 :         if (gdt.address == (unsigned long)fixmap_gdt) {
     253                 :          0 :                 load_direct_gdt(cpu);
     254                 :          0 :                 restore = 1;
     255                 :            :         }
     256                 :          0 :         asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
     257                 :         21 :         if (restore)
     258                 :          0 :                 load_fixmap_gdt(cpu);
     259                 :         21 : }
     260                 :            : #else
     261                 :            : static inline void native_load_tr_desc(void)
     262                 :            : {
     263                 :            :         asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
     264                 :            : }
     265                 :            : #endif
     266                 :            : 
     267                 :          0 : static inline unsigned long native_store_tr(void)
     268                 :            : {
     269                 :          0 :         unsigned long tr;
     270                 :            : 
     271                 :          0 :         asm volatile("str %0":"=r" (tr));
     272                 :            : 
     273                 :          0 :         return tr;
     274                 :            : }
     275                 :            : 
     276                 :     610834 : static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
     277                 :            : {
     278                 :     610834 :         struct desc_struct *gdt = get_cpu_gdt_rw(cpu);
     279                 :     610834 :         unsigned int i;
     280                 :            : 
     281         [ +  + ]:    2443336 :         for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
     282                 :    1832502 :                 gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
     283                 :            : }
     284                 :            : 
     285                 :            : DECLARE_PER_CPU(bool, __tss_limit_invalid);
     286                 :            : 
     287                 :          0 : static inline void force_reload_TR(void)
     288                 :            : {
     289                 :          0 :         struct desc_struct *d = get_current_gdt_rw();
     290                 :          0 :         tss_desc tss;
     291                 :            : 
     292                 :          0 :         memcpy(&tss, &d[GDT_ENTRY_TSS], sizeof(tss_desc));
     293                 :            : 
     294                 :            :         /*
     295                 :            :          * LTR requires an available TSS, and the TSS is currently
     296                 :            :          * busy.  Make it be available so that LTR will work.
     297                 :            :          */
     298                 :          0 :         tss.type = DESC_TSS;
     299                 :          0 :         write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS);
     300                 :            : 
     301                 :          0 :         load_TR_desc();
     302                 :          0 :         this_cpu_write(__tss_limit_invalid, false);
     303                 :          0 : }
     304                 :            : 
     305                 :            : /*
     306                 :            :  * Call this if you need the TSS limit to be correct, which should be the case
     307                 :            :  * if and only if you have TIF_IO_BITMAP set or you're switching to a task
     308                 :            :  * with TIF_IO_BITMAP set.
     309                 :            :  */
     310                 :          0 : static inline void refresh_tss_limit(void)
     311                 :            : {
     312                 :          0 :         DEBUG_LOCKS_WARN_ON(preemptible());
     313                 :            : 
     314         [ #  # ]:          0 :         if (unlikely(this_cpu_read(__tss_limit_invalid)))
     315                 :          0 :                 force_reload_TR();
     316                 :            : }
     317                 :            : 
     318                 :            : /*
     319                 :            :  * If you do something evil that corrupts the cached TSS limit (I'm looking
     320                 :            :  * at you, VMX exits), call this function.
     321                 :            :  *
     322                 :            :  * The optimization here is that the TSS limit only matters for Linux if the
     323                 :            :  * IO bitmap is in use.  If the TSS limit gets forced to its minimum value,
     324                 :            :  * everything works except that IO bitmap will be ignored and all CPL 3 IO
     325                 :            :  * instructions will #GP, which is exactly what we want for normal tasks.
     326                 :            :  */
     327                 :            : static inline void invalidate_tss_limit(void)
     328                 :            : {
     329                 :            :         DEBUG_LOCKS_WARN_ON(preemptible());
     330                 :            : 
     331                 :            :         if (unlikely(test_thread_flag(TIF_IO_BITMAP)))
     332                 :            :                 force_reload_TR();
     333                 :            :         else
     334                 :            :                 this_cpu_write(__tss_limit_invalid, true);
     335                 :            : }
     336                 :            : 
     337                 :            : /* This intentionally ignores lm, since 32-bit apps don't have that field. */
     338                 :            : #define LDT_empty(info)                                 \
     339                 :            :         ((info)->base_addr           == 0    &&      \
     340                 :            :          (info)->limit                       == 0    &&      \
     341                 :            :          (info)->contents            == 0    &&      \
     342                 :            :          (info)->read_exec_only              == 1    &&      \
     343                 :            :          (info)->seg_32bit           == 0    &&      \
     344                 :            :          (info)->limit_in_pages              == 0    &&      \
     345                 :            :          (info)->seg_not_present     == 1    &&      \
     346                 :            :          (info)->useable             == 0)
     347                 :            : 
     348                 :            : /* Lots of programs expect an all-zero user_desc to mean "no segment at all". */
     349                 :          0 : static inline bool LDT_zero(const struct user_desc *info)
     350                 :            : {
     351                 :          0 :         return (info->base_addr              == 0 &&
     352   [ #  #  #  # ]:          0 :                 info->limit          == 0 &&
     353                 :            :                 info->contents               == 0 &&
     354                 :            :                 info->read_exec_only == 0 &&
     355                 :            :                 info->seg_32bit              == 0 &&
     356                 :            :                 info->limit_in_pages == 0 &&
     357   [ #  #  #  #  :          0 :                 info->seg_not_present        == 0 &&
          #  #  #  #  #  
                #  #  # ]
     358                 :            :                 info->useable                == 0);
     359                 :            : }
     360                 :            : 
     361                 :         21 : static inline void clear_LDT(void)
     362                 :            : {
     363                 :         21 :         set_ldt(NULL, 0);
     364                 :         21 : }
     365                 :            : 
     366                 :          0 : static inline unsigned long get_desc_base(const struct desc_struct *desc)
     367                 :            : {
     368         [ #  # ]:          0 :         return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
     369                 :            : }
     370                 :            : 
     371                 :            : static inline void set_desc_base(struct desc_struct *desc, unsigned long base)
     372                 :            : {
     373                 :            :         desc->base0 = base & 0xffff;
     374                 :            :         desc->base1 = (base >> 16) & 0xff;
     375                 :            :         desc->base2 = (base >> 24) & 0xff;
     376                 :            : }
     377                 :            : 
     378                 :          0 : static inline unsigned long get_desc_limit(const struct desc_struct *desc)
     379                 :            : {
     380         [ #  # ]:          0 :         return desc->limit0 | (desc->limit1 << 16);
     381                 :            : }
     382                 :            : 
     383                 :            : static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
     384                 :            : {
     385                 :            :         desc->limit0 = limit & 0xffff;
     386                 :            :         desc->limit1 = (limit >> 16) & 0xf;
     387                 :            : }
     388                 :            : 
     389                 :            : void update_intr_gate(unsigned int n, const void *addr);
     390                 :            : void alloc_intr_gate(unsigned int n, const void *addr);
     391                 :            : 
     392                 :            : extern unsigned long system_vectors[];
     393                 :            : 
     394                 :            : #ifdef CONFIG_X86_64
     395                 :            : DECLARE_PER_CPU(u32, debug_idt_ctr);
     396                 :         21 : static inline bool is_debug_idt_enabled(void)
     397                 :            : {
     398   [ +  -  -  -  :         21 :         if (this_cpu_read(debug_idt_ctr))
                   -  - ]
     399                 :          0 :                 return true;
     400                 :            : 
     401                 :            :         return false;
     402                 :            : }
     403                 :            : 
     404                 :          0 : static inline void load_debug_idt(void)
     405                 :            : {
     406                 :          0 :         load_idt((const struct desc_ptr *)&debug_idt_descr);
     407                 :          0 : }
     408                 :            : #else
     409                 :            : static inline bool is_debug_idt_enabled(void)
     410                 :            : {
     411                 :            :         return false;
     412                 :            : }
     413                 :            : 
     414                 :            : static inline void load_debug_idt(void)
     415                 :            : {
     416                 :            : }
     417                 :            : #endif
     418                 :            : 
     419                 :            : /*
     420                 :            :  * The load_current_idt() must be called with interrupts disabled
     421                 :            :  * to avoid races. That way the IDT will always be set back to the expected
     422                 :            :  * descriptor. It's also called when a CPU is being initialized, and
     423                 :            :  * that doesn't need to disable interrupts, as nothing should be
     424                 :            :  * bothering the CPU then.
     425                 :            :  */
     426                 :         21 : static inline void load_current_idt(void)
     427                 :            : {
     428                 :         21 :         if (is_debug_idt_enabled())
     429                 :          0 :                 load_debug_idt();
     430                 :            :         else
     431                 :         21 :                 load_idt((const struct desc_ptr *)&idt_descr);
     432                 :            : }
     433                 :            : 
     434                 :            : extern void idt_setup_early_handler(void);
     435                 :            : extern void idt_setup_early_traps(void);
     436                 :            : extern void idt_setup_traps(void);
     437                 :            : extern void idt_setup_apic_and_irq_gates(void);
     438                 :            : 
     439                 :            : #ifdef CONFIG_X86_64
     440                 :            : extern void idt_setup_early_pf(void);
     441                 :            : extern void idt_setup_ist_traps(void);
     442                 :            : extern void idt_setup_debugidt_traps(void);
     443                 :            : #else
     444                 :            : static inline void idt_setup_early_pf(void) { }
     445                 :            : static inline void idt_setup_ist_traps(void) { }
     446                 :            : static inline void idt_setup_debugidt_traps(void) { }
     447                 :            : #endif
     448                 :            : 
     449                 :            : extern void idt_invalidate(void *addr);
     450                 :            : 
     451                 :            : #endif /* _ASM_X86_DESC_H */

Generated by: LCOV version 1.14