Skip to contentSkip to conversation

x86/paravirt/xen: properly fill out the ldt ops

PATCH Applied Jeremy Fitzhardinge 2 participants 2 messages Jul 23, 2008 – Jul 24, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 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.

---

arch/x86/kernel/ldt.c      |    9 ++++++++-
arch/x86/kernel/paravirt.c |    4 ++++
arch/x86/xen/enlighten.c   |   23 +++++++++++++++++++++++
include/asm-x86/desc.h     |   10 +++++++++-
include/asm-x86/paravirt.h |   13 +++++++++++++
5 files changed, 57 insertions(+), 2 deletions(-)

===================================================================

arch/x86/kernel/ldt.c +0 -0
@@ -52,6 +52,8 @@
	memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
	       (mincount - oldsize) * LDT_ENTRY_SIZE);

+ paravirt_alloc_ldt(newldt, mincount);
+

#ifdef CONFIG_X86_64
	/* CHECKME: Do we really need this ? */
	wmb();
@@ -76,6 +78,7 @@
#endif
	}
	if (oldsize) {
+		paravirt_free_ldt(oldldt, oldsize);
		if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
			vfree(oldldt);
		else
@@ -87,10 +90,13 @@
static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
{
	int err = alloc_ldt(new, old->size, 0);

+ int i;

	if (err < 0)
		return err;
-	memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE);
+
+	for(i = 0; i < old->size; i++)
+		write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
	return 0;
}

@@ -127,6 +133,7 @@

		if (mm == current->active_mm)
			clear_LDT();
#endif
+		paravirt_free_ldt(mm->context.ldt, mm->context.size);
		if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
			vfree(mm->context.ldt);
		else

===================================================================

arch/x86/kernel/paravirt.c +0 -0
@@ -350,6 +350,10 @@

.write_ldt_entry = native_write_ldt_entry, .write_gdt_entry = native_write_gdt_entry, .write_idt_entry = native_write_idt_entry,
+
+ .alloc_ldt = paravirt_nop,
+ .free_ldt = paravirt_nop,
+

	.load_sp0 = native_load_sp0,

#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
===================================================================

arch/x86/xen/enlighten.c +0 -0
@@ -327,6 +327,26 @@

static unsigned long xen_store_tr(void)

{
	return 0;

+}
+
+static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{
+ unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
+ void *v = ldt;
+ int i;
+
+ for(i = 0; i < pages; i += PAGE_SIZE)
+ make_lowmem_page_readonly(v + i);
+}
+
+static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) +{
+ unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
+ void *v = ldt;
+ int i;
+
+ for(i = 0; i < pages; i += PAGE_SIZE)
+ make_lowmem_page_readwrite(v + i);
}

static void xen_set_ldt(const void *addr, unsigned entries) @@ -1269,6 +1289,9 @@
.load_gs_index = xen_load_gs_index,
#endif

+ .alloc_ldt = xen_alloc_ldt,
+ .free_ldt = xen_free_ldt,
+
.store_gdt = native_store_gdt,
.store_idt = native_store_idt,
.store_tr = xen_store_tr,
===================================================================

include/asm-x86/desc.h +0 -0
@@ -97,7 +97,15 @@

native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) \
native_write_idt_entry(dt, entry, g)
-#endif
+
+static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{
+}
+
+static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) +{
+}
+#endif /* CONFIG_PARAVIRT */

static inline void native_write_idt_entry(gate_desc *idt, int entry,
const gate_desc *gate)
===================================================================

include/asm-x86/paravirt.h +0 -0
@@ -124,6 +124,9 @@
				int entrynum, const void *desc, int size);
	void (*write_idt_entry)(gate_desc *,
				int entrynum, const gate_desc *gate);
+	void (*alloc_ldt)(struct desc_struct *ldt, unsigned entries);
+	void (*free_ldt)(struct desc_struct *ldt, unsigned entries);
+
	void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);

	void (*set_iopl_mask)(unsigned mask);
@@ -819,6 +822,16 @@
	(aux) = __aux;					\
} while (0)

+static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries) +{
+ PVOP_VCALL2(pv_cpu_ops.alloc_ldt, ldt, entries);
+}
+
+static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) +{
+ PVOP_VCALL2(pv_cpu_ops.free_ldt, ldt, entries);
+}
+
static inline void load_TR_desc(void)

{
	PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
Applied
#1 lore raw
Quoted 3 lines · Jeremy Fitzhardinge

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.

applied to tip/x86/xen, thanks Jeremy.

Ingo