[PATCH] abstract out bits of ldt.c

From: Martin J. Bligh
Date: Sun Aug 07 2005 - 18:20:25 EST


Starting on the work to merge xen cleanly as a subarch.
Introduce make_pages_readonly and make_pages_writable where appropriate
for Xen, defined as a no-op on other subarches. Same for
add_context_to_unpinned and del_context_from_unpinned.
Abstract out install_ldt_entry().

This will do have no effect whatsover on platforms other than xen.

Compile-tested with every config I can find. Boot tested on i386.

diff -aurpN -X /home/fletch/.diff.exclude virgin/arch/i386/kernel/ldt.c xen-ldt.c/arch/i386/kernel/ldt.c
--- virgin/arch/i386/kernel/ldt.c 2004-10-24 19:27:13.000000000 -0700
+++ xen-ldt.c/arch/i386/kernel/ldt.c 2005-08-07 10:45:49.000000000 -0700
@@ -18,6 +18,7 @@
#include <asm/system.h>
#include <asm/ldt.h>
#include <asm/desc.h>
+#include <mach_ldt.h>

#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
static void flush_ldt(void *null)
@@ -58,16 +59,22 @@ static int alloc_ldt(mm_context_t *pc, i
#ifdef CONFIG_SMP
cpumask_t mask;
preempt_disable();
+ make_pages_readonly(pc->ldt, (pc->size * LDT_ENTRY_SIZE) /
+ PAGE_SIZE);
load_LDT(pc);
mask = cpumask_of_cpu(smp_processor_id());
if (!cpus_equal(current->mm->cpu_vm_mask, mask))
smp_call_function(flush_ldt, NULL, 1, 1);
preempt_enable();
#else
+ make_pages_readonly(pc->ldt, (pc->size * LDT_ENTRY_SIZE) /
+ PAGE_SIZE);
load_LDT(pc);
#endif
}
if (oldsize) {
+ make_pages_writable(oldldt, (oldsize * LDT_ENTRY_SIZE) /
+ PAGE_SIZE);
if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
vfree(oldldt);
else
@@ -82,6 +89,8 @@ static inline int copy_ldt(mm_context_t
if (err < 0)
return err;
memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
+ make_pages_readonly(new->ldt, (new->size * LDT_ENTRY_SIZE) /
+ PAGE_SIZE);
return 0;
}

@@ -94,14 +103,16 @@ int init_new_context(struct task_struct
struct mm_struct * old_mm;
int retval = 0;

+ memset(&mm->context, 0, sizeof(mm->context));
init_MUTEX(&mm->context.sem);
- mm->context.size = 0;
old_mm = current->mm;
if (old_mm && old_mm->context.size > 0) {
down(&old_mm->context.sem);
retval = copy_ldt(&mm->context, &old_mm->context);
up(&old_mm->context.sem);
}
+ if (retval == 0)
+ add_context_to_unpinned(mm);
return retval;
}

@@ -113,12 +124,16 @@ void destroy_context(struct mm_struct *m
if (mm->context.size) {
if (mm == current->active_mm)
clear_LDT();
+ make_pages_writable(mm->context.ldt,
+ (mm->context.size * LDT_ENTRY_SIZE) /
+ PAGE_SIZE);
if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
vfree(mm->context.ldt);
else
kfree(mm->context.ldt);
mm->context.size = 0;
}
+ del_context_from_unpinned(mm);
}

static int read_ldt(void __user * ptr, unsigned long bytecount)
@@ -223,9 +238,7 @@ static int write_ldt(void __user * ptr,

/* Install the new entry ... */
install:
- *lp = entry_1;
- *(lp+1) = entry_2;
- error = 0;
+ error = install_ldt_entry(lp, entry_1, entry_2);

out_unlock:
up(&mm->context.sem);
diff -aurpN -X /home/fletch/.diff.exclude virgin/include/asm-i386/mach-default/mach_ldt.h xen-ldt.c/include/asm-i386/mach-default/mach_ldt.h
--- virgin/include/asm-i386/mach-default/mach_ldt.h 1969-12-31 16:00:00.000000000 -0800
+++ xen-ldt.c/include/asm-i386/mach-default/mach_ldt.h 2005-08-07 10:43:58.000000000 -0700
@@ -0,0 +1,27 @@
+#ifndef __ASM_MACH_LDT_H
+#define __ASM_MACH_LDT_H
+
+static inline void make_pages_readonly(void *va, unsigned int nr)
+{
+}
+
+static inline void make_pages_writable(void *va, unsigned int nr)
+{
+}
+
+static inline void add_context_to_unpinned(struct mm_struct *mm)
+{
+}
+
+static inline void del_context_from_unpinned(struct mm_struct *mm)
+{
+}
+
+static inline int install_ldt_entry (__u32 *lp, __u32 entry_1, __u32 entry_2)
+{
+ *lp = entry_1;
+ *(lp+1) = entry_2;
+ return 0;
+}
+
+#endif /* __ASM_MACH_LDT_H */
diff -aurpN -X /home/fletch/.diff.exclude virgin/include/asm-i386/mach-xen/mach_ldt.h xen-ldt.c/include/asm-i386/mach-xen/mach_ldt.h
--- virgin/include/asm-i386/mach-xen/mach_ldt.h 1969-12-31 16:00:00.000000000 -0800
+++ xen-ldt.c/include/asm-i386/mach-xen/mach_ldt.h 2005-08-07 10:44:45.000000000 -0700
@@ -0,0 +1,27 @@
+#ifndef __ASM_MACH_LDT_H
+#define __ASM_MACH_LDT_H
+
+static inline void add_context_to_unpinned(struct mm_struct *mm)
+{
+ spin_lock(&mm_unpinned_lock);
+ list_add(&mm->context.unpinned, &mm_unpinned);
+ spin_unlock(&mm_unpinned_lock);
+}
+
+static inline void del_context_from_unpinned(struct mm_struct *mm)
+{
+ if (!mm->context.pinned) {
+ spin_lock(&mm_unpinned_lock);
+ list_del(&mm->context.unpinned);
+ spin_unlock(&mm_unpinned_lock);
+ }
+}
+
+static inline int install_ldt_entry (__u32 *lp, __u32 entry_1, __u32 entry_2)
+{
+ unsigned long mach_lp = arbitrary_virt_to_machine(lp);
+
+ return HYPERVISOR_update_descriptor(mach_lp, entry_1, entry_2);
+}
+
+#endif /* __ASM_MACH_LDT_H */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/