|
@@ -4,6 +4,7 @@
|
|
|
#include <asm/desc_defs.h>
|
|
|
#include <asm/ldt.h>
|
|
|
#include <asm/mmu.h>
|
|
|
+#include <asm/fixmap.h>
|
|
|
|
|
|
#include <linux/smp.h>
|
|
|
#include <linux/percpu.h>
|
|
@@ -38,6 +39,7 @@ 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[];
|
|
|
+extern pgprot_t pg_fixmap_gdt_flags;
|
|
|
|
|
|
struct gdt_page {
|
|
|
struct desc_struct gdt[GDT_ENTRIES];
|
|
@@ -45,11 +47,57 @@ struct gdt_page {
|
|
|
|
|
|
DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
|
|
|
|
|
|
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
|
|
|
+/* Provide the original GDT */
|
|
|
+static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu)
|
|
|
{
|
|
|
return per_cpu(gdt_page, cpu).gdt;
|
|
|
}
|
|
|
|
|
|
+static inline unsigned long get_cpu_gdt_rw_vaddr(unsigned int cpu)
|
|
|
+{
|
|
|
+ return (unsigned long)get_cpu_gdt_rw(cpu);
|
|
|
+}
|
|
|
+
|
|
|
+/* Provide the current original GDT */
|
|
|
+static inline struct desc_struct *get_current_gdt_rw(void)
|
|
|
+{
|
|
|
+ return this_cpu_ptr(&gdt_page)->gdt;
|
|
|
+}
|
|
|
+
|
|
|
+static inline unsigned long get_current_gdt_rw_vaddr(void)
|
|
|
+{
|
|
|
+ return (unsigned long)get_current_gdt_rw();
|
|
|
+}
|
|
|
+
|
|
|
+/* 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;
|
|
|
+}
|
|
|
+
|
|
|
+/* 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);
|
|
|
+}
|
|
|
+
|
|
|
+static inline unsigned long get_cpu_gdt_ro_vaddr(int cpu)
|
|
|
+{
|
|
|
+ return (unsigned long)get_cpu_gdt_ro(cpu);
|
|
|
+}
|
|
|
+
|
|
|
+/* Provide the current read-only GDT */
|
|
|
+static inline struct desc_struct *get_current_gdt_ro(void)
|
|
|
+{
|
|
|
+ return get_cpu_gdt_ro(smp_processor_id());
|
|
|
+}
|
|
|
+
|
|
|
+static inline unsigned long get_current_gdt_ro_vaddr(void)
|
|
|
+{
|
|
|
+ return (unsigned long)get_current_gdt_ro();
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
|
|
static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
|
|
@@ -174,7 +222,7 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t
|
|
|
|
|
|
static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
|
|
|
{
|
|
|
- struct desc_struct *d = get_cpu_gdt_table(cpu);
|
|
|
+ struct desc_struct *d = get_cpu_gdt_rw(cpu);
|
|
|
tss_desc tss;
|
|
|
|
|
|
set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
|
|
@@ -194,7 +242,7 @@ static inline void native_set_ldt(const void *addr, unsigned int entries)
|
|
|
|
|
|
set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,
|
|
|
entries * LDT_ENTRY_SIZE - 1);
|
|
|
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
|
|
|
+ write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_LDT,
|
|
|
&ldt, DESC_LDT);
|
|
|
asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
|
|
|
}
|
|
@@ -209,7 +257,7 @@ DECLARE_PER_CPU(bool, __tss_limit_invalid);
|
|
|
|
|
|
static inline void force_reload_TR(void)
|
|
|
{
|
|
|
- struct desc_struct *d = get_cpu_gdt_table(smp_processor_id());
|
|
|
+ struct desc_struct *d = get_current_gdt_rw();
|
|
|
tss_desc tss;
|
|
|
|
|
|
memcpy(&tss, &d[GDT_ENTRY_TSS], sizeof(tss_desc));
|
|
@@ -288,7 +336,7 @@ static inline unsigned long native_store_tr(void)
|
|
|
|
|
|
static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
|
|
|
{
|
|
|
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
|
|
|
+ struct desc_struct *gdt = get_cpu_gdt_rw(cpu);
|
|
|
unsigned int i;
|
|
|
|
|
|
for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
|