cregit-Linux how code gets into the kernel

Release 4.14 arch/x86/include/asm/desc.h

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_DESC_H

#define _ASM_X86_DESC_H

#include <asm/desc_defs.h>
#include <asm/ldt.h>
#include <asm/mmu.h>
#include <asm/fixmap.h>
#include <asm/irq_vectors.h>

#include <linux/smp.h>
#include <linux/percpu.h>


static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info) { desc->limit0 = info->limit & 0x0ffff; desc->base0 = (info->base_addr & 0x0000ffff); desc->base1 = (info->base_addr & 0x00ff0000) >> 16; desc->type = (info->read_exec_only ^ 1) << 1; desc->type |= info->contents << 2; desc->s = 1; desc->dpl = 0x3; desc->p = info->seg_not_present ^ 1; desc->limit1 = (info->limit & 0xf0000) >> 16; desc->avl = info->useable; desc->d = info->seg_32bit; desc->g = info->limit_in_pages; desc->base2 = (info->base_addr & 0xff000000) >> 24; /* * Don't allow setting of the lm bit. It would confuse * user_64bit_mode and would get overridden by sysret anyway. */ desc->l = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa14893.08%116.67%
Jeremy Fitzhardinge63.77%116.67%
Ingo Molnar21.26%116.67%
Thomas Gleixner10.63%116.67%
Roland McGrath10.63%116.67%
Andrew Lutomirski10.63%116.67%
Total159100.00%6100.00%

extern struct desc_ptr idt_descr; extern gate_desc idt_table[]; extern const struct desc_ptr debug_idt_descr; extern gate_desc debug_idt_table[]; struct gdt_page { struct desc_struct gdt[GDT_ENTRIES]; } __attribute__((aligned(PAGE_SIZE))); DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page); /* Provide the original GDT */
static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu) { return per_cpu(gdt_page, cpu).gdt; }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa2295.65%266.67%
Thomas Garnier14.35%133.33%
Total23100.00%3100.00%

/* Provide the current original GDT */
static inline struct desc_struct *get_current_gdt_rw(void) { return this_cpu_ptr(&gdt_page)->gdt; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier20100.00%1100.00%
Total20100.00%1100.00%

/* Get the fixmap index for a specific processor */
static inline unsigned int get_cpu_gdt_ro_index(int cpu) { return FIX_GDT_REMAP_BEGIN + cpu; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier16100.00%1100.00%
Total16100.00%1100.00%

/* Provide the fixmap address of the remapped GDT */
static inline struct desc_struct *get_cpu_gdt_ro(int cpu) { unsigned int idx = get_cpu_gdt_ro_index(cpu); return (struct desc_struct *)__fix_to_virt(idx); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier32100.00%1100.00%
Total32100.00%1100.00%

/* Provide the current read-only GDT */
static inline struct desc_struct *get_current_gdt_ro(void) { return get_cpu_gdt_ro(smp_processor_id()); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier18100.00%1100.00%
Total18100.00%1100.00%

/* Provide the physical address of the GDT page. */
static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu) { return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu)); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lutomirski20100.00%1100.00%
Total20100.00%1100.00%


static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, unsigned dpl, unsigned ist, unsigned seg) { gate->offset_low = (u16) func; gate->bits.p = 1; gate->bits.dpl = dpl; gate->bits.zero = 0; gate->bits.type = type; gate->offset_middle = (u16) (func >> 16); #ifdef CONFIG_X86_64 gate->segment = __KERNEL_CS; gate->bits.ist = ist; gate->reserved = 0; gate->offset_high = (u32) (func >> 32); #else gate->segment = seg; gate->bits.ist = 0; #endif }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa8562.96%266.67%
Thomas Gleixner5037.04%133.33%
Total135100.00%3100.00%


static inline int desc_empty(const void *ptr) { const u32 *desc = ptr; return !(desc[0] | desc[1]); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa33100.00%1100.00%
Total33100.00%1100.00%

#ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> #else #define load_TR_desc() native_load_tr_desc() #define load_gdt(dtr) native_load_gdt(dtr) #define load_idt(dtr) native_load_idt(dtr) #define load_tr(tr) asm volatile("ltr %0"::"m" (tr)) #define load_ldt(ldt) asm volatile("lldt %0"::"m" (ldt)) #define store_gdt(dtr) native_store_gdt(dtr) #define store_tr(tr) (tr = native_store_tr()) #define load_TLS(t, cpu) native_load_tls(t, cpu) #define set_ldt native_set_ldt #define write_ldt_entry(dt, entry, desc) native_write_ldt_entry(dt, entry, desc) #define write_gdt_entry(dt, entry, desc, type) native_write_gdt_entry(dt, entry, desc, type) #define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries) { }

Contributors

PersonTokensPropCommitsCommitProp
Jeremy Fitzhardinge14100.00%1100.00%
Total14100.00%1100.00%


static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) { }

Contributors

PersonTokensPropCommitsCommitProp
Jeremy Fitzhardinge14100.00%1100.00%
Total14100.00%1100.00%

#endif /* CONFIG_PARAVIRT */ #define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate) { memcpy(&idt[entry], gate, sizeof(*gate)); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa36100.00%1100.00%
Total36100.00%1100.00%


static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry, const void *desc) { memcpy(&ldt[entry], desc, 8); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa33100.00%1100.00%
Total33100.00%1100.00%


static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc, int type) { unsigned int size; switch (type) { case DESC_TSS: size = sizeof(tss_desc); break; case DESC_LDT: size = sizeof(ldt_desc); break; default: size = sizeof(*gdt); break; } memcpy(&gdt[entry], desc, size); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa7697.44%150.00%
Ingo Molnar22.56%150.00%
Total78100.00%2100.00%


static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size) { struct ldttss_desc *desc = d; memset(desc, 0, sizeof(*desc)); desc->limit0 = (u16) size; desc->base0 = (u16) addr; desc->base1 = (addr >> 16) & 0xFF; desc->type = type; desc->p = 1; desc->limit1 = (size >> 16) & 0xF; desc->base2 = (addr >> 24) & 0xFF; #ifdef CONFIG_X86_64 desc->base3 = (u32) (addr >> 32); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa10584.00%360.00%
Thomas Gleixner2016.00%240.00%
Total125100.00%5100.00%


static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr) { struct desc_struct *d = get_cpu_gdt_rw(cpu); tss_desc tss; set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS, __KERNEL_TSS_LIMIT); write_gdt_entry(d, entry, &tss, DESC_TSS); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa5796.61%250.00%
Andrew Lutomirski11.69%125.00%
Thomas Garnier11.69%125.00%
Total59100.00%4100.00%

#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
static inline void native_set_ldt(const void *addr, unsigned int entries) { if (likely(entries == 0)) asm volatile("lldt %w0"::"q" (0)); else { unsigned cpu = smp_processor_id(); ldt_desc ldt; set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT, entries * LDT_ENTRY_SIZE - 1); write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_LDT, &ldt, DESC_LDT); asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8)); } }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa7292.31%240.00%
Joe Perches45.13%120.00%
Thomas Garnier11.28%120.00%
Michael Karcher11.28%120.00%
Total78100.00%5100.00%


static inline void native_load_gdt(const struct desc_ptr *dtr) { asm volatile("lgdt %0"::"m" (*dtr)); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier16100.00%1100.00%
Total16100.00%1100.00%


static inline void native_load_idt(const struct desc_ptr *dtr) { asm volatile("lidt %0"::"m" (*dtr)); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier16100.00%1100.00%
Total16100.00%1100.00%


static inline void native_store_gdt(struct desc_ptr *dtr) { asm volatile("sgdt %0":"=m" (*dtr)); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier15100.00%1100.00%
Total15100.00%1100.00%


static inline void store_idt(struct desc_ptr *dtr) { asm volatile("sidt %0":"=m" (*dtr)); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier1493.33%150.00%
Juergen Gross16.67%150.00%
Total15100.00%2100.00%

/* * The LTR instruction marks the TSS GDT entry as busy. On 64-bit, the GDT is * a read-only remapping. To prevent a page fault, the GDT is switched to the * original writeable version when needed. */ #ifdef CONFIG_X86_64
static inline void native_load_tr_desc(void) { struct desc_ptr gdt; int cpu = raw_smp_processor_id(); bool restore = 0; struct desc_struct *fixmap_gdt; native_store_gdt(&gdt); fixmap_gdt = get_cpu_gdt_ro(cpu); /* * If the current GDT is the read-only fixmap, swap to the original * writeable version. Swap back at the end. */ if (gdt.address == (unsigned long)fixmap_gdt) { load_direct_gdt(cpu); restore = 1; } asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); if (restore) load_fixmap_gdt(cpu); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier78100.00%1100.00%
Total78100.00%1100.00%

#else
static inline void native_load_tr_desc(void) { asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa12100.00%1100.00%
Total12100.00%1100.00%

#endif
static inline unsigned long native_store_tr(void) { unsigned long tr; asm volatile("str %0":"=r" (tr)); return tr; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier20100.00%1100.00%
Total20100.00%1100.00%


static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) { struct desc_struct *gdt = get_cpu_gdt_rw(cpu); unsigned int i; for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Garnier57100.00%1100.00%
Total57100.00%1100.00%

DECLARE_PER_CPU(bool, __tss_limit_invalid);
static inline void force_reload_TR(void) { struct desc_struct *d = get_current_gdt_rw(); tss_desc tss; memcpy(&tss, &d[GDT_ENTRY_TSS], sizeof(tss_desc)); /* * LTR requires an available TSS, and the TSS is currently * busy. Make it be available so that LTR will work. */ tss.type = DESC_TSS; write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS); load_TR_desc(); this_cpu_write(__tss_limit_invalid, false); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lutomirski6598.48%266.67%
Thomas Garnier11.52%133.33%
Total66100.00%3100.00%

/* * Call this if you need the TSS limit to be correct, which should be the case * if and only if you have TIF_IO_BITMAP set or you're switching to a task * with TIF_IO_BITMAP set. */
static inline void refresh_tss_limit(void) { DEBUG_LOCKS_WARN_ON(preemptible()); if (unlikely(this_cpu_read(__tss_limit_invalid))) force_reload_TR(); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lutomirski28100.00%2100.00%
Total28100.00%2100.00%

/* * If you do something evil that corrupts the cached TSS limit (I'm looking * at you, VMX exits), call this function. * * The optimization here is that the TSS limit only matters for Linux if the * IO bitmap is in use. If the TSS limit gets forced to its minimum value, * everything works except that IO bitmap will be ignored and all CPL 3 IO * instructions will #GP, which is exactly what we want for normal tasks. */
static inline void invalidate_tss_limit(void) { DEBUG_LOCKS_WARN_ON(preemptible()); if (unlikely(test_thread_flag(TIF_IO_BITMAP))) force_reload_TR(); else this_cpu_write(__tss_limit_invalid, true); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lutomirski36100.00%2100.00%
Total36100.00%2100.00%

/* This intentionally ignores lm, since 32-bit apps don't have that field. */ #define LDT_empty(info) \ ((info)->base_addr == 0 && \ (info)->limit == 0 && \ (info)->contents == 0 && \ (info)->read_exec_only == 1 && \ (info)->seg_32bit == 0 && \ (info)->limit_in_pages == 0 && \ (info)->seg_not_present == 1 && \ (info)->useable == 0) /* Lots of programs expect an all-zero user_desc to mean "no segment at all". */
static inline bool LDT_zero(const struct user_desc *info) { return (info->base_addr == 0 && info->limit == 0 && info->contents == 0 && info->read_exec_only == 0 && info->seg_32bit == 0 && info->limit_in_pages == 0 && info->seg_not_present == 0 && info->useable == 0); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lutomirski64100.00%1100.00%
Total64100.00%1100.00%


static inline void clear_LDT(void) { set_ldt(NULL, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa16100.00%1100.00%
Total16100.00%1100.00%


static inline unsigned long get_desc_base(const struct desc_struct *desc) { return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24)); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa3886.36%133.33%
Chris Lalancette511.36%133.33%
Roland McGrath12.27%133.33%
Total44100.00%3100.00%


static inline void set_desc_base(struct desc_struct *desc, unsigned long base) { desc->base0 = base & 0xffff; desc->base1 = (base >> 16) & 0xff; desc->base2 = (base >> 24) & 0xff; }

Contributors

PersonTokensPropCommitsCommitProp
Akinobu Mita48100.00%1100.00%
Total48100.00%1100.00%


static inline unsigned long get_desc_limit(const struct desc_struct *desc) { return desc->limit0 | (desc->limit1 << 16); }

Contributors

PersonTokensPropCommitsCommitProp
Roland McGrath2696.30%150.00%
Thomas Gleixner13.70%150.00%
Total27100.00%2100.00%


static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) { desc->limit0 = limit & 0xffff; desc->limit1 = (limit >> 16) & 0xf; }

Contributors

PersonTokensPropCommitsCommitProp
Akinobu Mita3597.22%150.00%
Thomas Gleixner12.78%150.00%
Total36100.00%2100.00%

void update_intr_gate(unsigned int n, const void *addr); void alloc_intr_gate(unsigned int n, const void *addr); extern unsigned long used_vectors[]; #ifdef CONFIG_X86_64 DECLARE_PER_CPU(u32, debug_idt_ctr);
static inline bool is_debug_idt_enabled(void) { if (this_cpu_read(debug_idt_ctr)) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi22100.00%1100.00%
Total22100.00%1100.00%


static inline void load_debug_idt(void) { load_idt((const struct desc_ptr *)&debug_idt_descr); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi21100.00%1100.00%
Total21100.00%1100.00%

#else
static inline bool is_debug_idt_enabled(void) { return false; }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi12100.00%1100.00%
Total12100.00%1100.00%


static inline void load_debug_idt(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi8100.00%1100.00%
Total8100.00%1100.00%

#endif /* * The load_current_idt() must be called with interrupts disabled * to avoid races. That way the IDT will always be set back to the expected * descriptor. It's also called when a CPU is being initialized, and * that doesn't need to disable interrupts, as nothing should be * bothering the CPU then. */
static inline void load_current_idt(void) { if (is_debug_idt_enabled()) load_debug_idt(); else load_idt((const struct desc_ptr *)&idt_descr); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi30100.00%1100.00%
Total30100.00%1100.00%

extern void idt_setup_early_handler(void); extern void idt_setup_early_traps(void); extern void idt_setup_traps(void); extern void idt_setup_apic_and_irq_gates(void); #ifdef CONFIG_X86_64 extern void idt_setup_early_pf(void); extern void idt_setup_ist_traps(void); extern void idt_setup_debugidt_traps(void); #else
static inline void idt_setup_early_pf(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Gleixner8100.00%1100.00%
Total8100.00%1100.00%


static inline void idt_setup_ist_traps(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Gleixner8100.00%1100.00%
Total8100.00%1100.00%


static inline void idt_setup_debugidt_traps(void) { }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Gleixner8100.00%1100.00%
Total8100.00%1100.00%

#endif extern void idt_invalidate(void *addr); #endif /* _ASM_X86_DESC_H */

Overall Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa91146.67%916.98%
Thomas Garnier32216.50%23.77%
Andrew Lutomirski22911.73%713.21%
Thomas Gleixner1748.91%1324.53%
Seiji Aguchi1226.25%35.66%
Akinobu Mita834.25%11.89%
Jeremy Fitzhardinge351.79%23.77%
Roland McGrath281.43%11.89%
Steven Rostedt90.46%23.77%
Jaswinder Singh Rajput70.36%11.89%
Joe Perches60.31%11.89%
Chris Lalancette50.26%11.89%
Ingo Molnar40.20%11.89%
Alan Mayer30.15%11.89%
Alex Shi30.15%11.89%
Yinghai Lu30.15%11.89%
H. Peter Anvin30.15%11.89%
Greg Kroah-Hartman10.05%11.89%
David Howells10.05%11.89%
Kees Cook10.05%11.89%
Juergen Gross10.05%11.89%
Michael Karcher10.05%11.89%
Total1952100.00%53100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.