aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-07-23 17:21:18 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-24 06:30:06 -0400
commit38ffbe66d59051fd9cfcfc8545f164700e2fa3bc (patch)
tree37e76db49cc86b3da550a62f36d101c7269d262e
parent338b9bb3adac0d2c5a1e180491d9b001d624c402 (diff)
x86/paravirt/xen: properly fill out the ldt ops
LTP testing showed that Xen does not properly implement sys_modify_ldt(). This patch does the final little bits needed to make the ldt work properly. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/ldt.c9
-rw-r--r--arch/x86/kernel/paravirt.c4
-rw-r--r--arch/x86/xen/enlighten.c23
-rw-r--r--include/asm-x86/desc.h10
-rw-r--r--include/asm-x86/paravirt.h13
5 files changed, 57 insertions, 2 deletions
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 3fee2aa50f3f..4895e0634d22 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -51,6 +51,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
51 memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, 51 memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
52 (mincount - oldsize) * LDT_ENTRY_SIZE); 52 (mincount - oldsize) * LDT_ENTRY_SIZE);
53 53
54 paravirt_alloc_ldt(newldt, mincount);
55
54#ifdef CONFIG_X86_64 56#ifdef CONFIG_X86_64
55 /* CHECKME: Do we really need this ? */ 57 /* CHECKME: Do we really need this ? */
56 wmb(); 58 wmb();
@@ -75,6 +77,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
75#endif 77#endif
76 } 78 }
77 if (oldsize) { 79 if (oldsize) {
80 paravirt_free_ldt(oldldt, oldsize);
78 if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) 81 if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
79 vfree(oldldt); 82 vfree(oldldt);
80 else 83 else
@@ -86,10 +89,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
86static inline int copy_ldt(mm_context_t *new, mm_context_t *old) 89static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
87{ 90{
88 int err = alloc_ldt(new, old->size, 0); 91 int err = alloc_ldt(new, old->size, 0);
92 int i;
89 93
90 if (err < 0) 94 if (err < 0)
91 return err; 95 return err;
92 memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); 96
97 for(i = 0; i < old->size; i++)
98 write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
93 return 0; 99 return 0;
94} 100}
95 101
@@ -126,6 +132,7 @@ void destroy_context(struct mm_struct *mm)
126 if (mm == current->active_mm) 132 if (mm == current->active_mm)
127 clear_LDT(); 133 clear_LDT();
128#endif 134#endif
135 paravirt_free_ldt(mm->context.ldt, mm->context.size);
129 if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) 136 if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
130 vfree(mm->context.ldt); 137 vfree(mm->context.ldt);
131 else 138 else
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 94da4d52d798..d8f2277be5a0 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -348,6 +348,10 @@ struct pv_cpu_ops pv_cpu_ops = {
348 .write_ldt_entry = native_write_ldt_entry, 348 .write_ldt_entry = native_write_ldt_entry,
349 .write_gdt_entry = native_write_gdt_entry, 349 .write_gdt_entry = native_write_gdt_entry,
350 .write_idt_entry = native_write_idt_entry, 350 .write_idt_entry = native_write_idt_entry,
351
352 .alloc_ldt = paravirt_nop,
353 .free_ldt = paravirt_nop,
354
351 .load_sp0 = native_load_sp0, 355 .load_sp0 = native_load_sp0,
352 356
353#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) 357#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 9ff6e3cbf08f..06219e60e9c8 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -325,6 +325,26 @@ static unsigned long xen_store_tr(void)
325 return 0; 325 return 0;
326} 326}
327 327
328static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
329{
330 unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
331 void *v = ldt;
332 int i;
333
334 for(i = 0; i < pages; i += PAGE_SIZE)
335 make_lowmem_page_readonly(v + i);
336}
337
338static void xen_free_ldt(struct desc_struct *ldt, unsigned entries)
339{
340 unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
341 void *v = ldt;
342 int i;
343
344 for(i = 0; i < pages; i += PAGE_SIZE)
345 make_lowmem_page_readwrite(v + i);
346}
347
328static void xen_set_ldt(const void *addr, unsigned entries) 348static void xen_set_ldt(const void *addr, unsigned entries)
329{ 349{
330 struct mmuext_op *op; 350 struct mmuext_op *op;
@@ -1220,6 +1240,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
1220 .load_gs_index = xen_load_gs_index, 1240 .load_gs_index = xen_load_gs_index,
1221#endif 1241#endif
1222 1242
1243 .alloc_ldt = xen_alloc_ldt,
1244 .free_ldt = xen_free_ldt,
1245
1223 .store_gdt = native_store_gdt, 1246 .store_gdt = native_store_gdt,
1224 .store_idt = native_store_idt, 1247 .store_idt = native_store_idt,
1225 .store_tr = xen_store_tr, 1248 .store_tr = xen_store_tr,
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index a44c4dc70590..24a524f5e1a2 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -97,7 +97,15 @@ static inline int desc_empty(const void *ptr)
97 native_write_gdt_entry(dt, entry, desc, type) 97 native_write_gdt_entry(dt, entry, desc, type)
98#define write_idt_entry(dt, entry, g) \ 98#define write_idt_entry(dt, entry, g) \
99 native_write_idt_entry(dt, entry, g) 99 native_write_idt_entry(dt, entry, g)
100#endif 100
101static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
102{
103}
104
105static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
106{
107}
108#endif /* CONFIG_PARAVIRT */
101 109
102static inline void native_write_idt_entry(gate_desc *idt, int entry, 110static inline void native_write_idt_entry(gate_desc *idt, int entry,
103 const gate_desc *gate) 111 const gate_desc *gate)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index fbbde93f12d6..db9b0647b346 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -124,6 +124,9 @@ struct pv_cpu_ops {
124 int entrynum, const void *desc, int size); 124 int entrynum, const void *desc, int size);
125 void (*write_idt_entry)(gate_desc *, 125 void (*write_idt_entry)(gate_desc *,
126 int entrynum, const gate_desc *gate); 126 int entrynum, const gate_desc *gate);
127 void (*alloc_ldt)(struct desc_struct *ldt, unsigned entries);
128 void (*free_ldt)(struct desc_struct *ldt, unsigned entries);
129
127 void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t); 130 void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
128 131
129 void (*set_iopl_mask)(unsigned mask); 132 void (*set_iopl_mask)(unsigned mask);
@@ -824,6 +827,16 @@ do { \
824 (aux) = __aux; \ 827 (aux) = __aux; \
825} while (0) 828} while (0)
826 829
830static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
831{
832 PVOP_VCALL2(pv_cpu_ops.alloc_ldt, ldt, entries);
833}
834
835static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
836{
837 PVOP_VCALL2(pv_cpu_ops.free_ldt, ldt, entries);
838}
839
827static inline void load_TR_desc(void) 840static inline void load_TR_desc(void)
828{ 841{
829 PVOP_VCALL0(pv_cpu_ops.load_tr_desc); 842 PVOP_VCALL0(pv_cpu_ops.load_tr_desc);