Index: linux-2.6.13/arch/i386/kernel/ldt.c ==================================================================--- linux-2.6.13.orig/arch/i386/kernel/ldt.c 2005-08-08 15:27:26.000000000 -0700 +++ linux-2.6.13/arch/i386/kernel/ldt.c 2005-08-08 21:13:19.000000000 -0700 @@ -18,6 +18,7 @@ #include <asm/system.h> #include <asm/ldt.h> #include <asm/desc.h> +#include <hypervisor_hooks.h> #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ static void flush_ldt(void *null) @@ -58,16 +59,22 @@ #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 @@ 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 @@ 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 @@ 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) Index: linux-2.6.13/include/asm-i386/mach-default/hypervisor_hooks.h ==================================================================--- linux-2.6.13.orig/include/asm-i386/mach-default/hypervisor_hooks.h 2005-08-08 21:12:55.000000000 -0700 +++ linux-2.6.13/include/asm-i386/mach-default/hypervisor_hooks.h 2005-08-08 21:13:19.000000000 -0700 @@ -0,0 +1,27 @@ +#ifndef __ASM_HYPERVISOR_HOOKS_H +#define __ASM_HYPERVISOR_HOOKS_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_HYPERVISOR_HOOKS_H */ Index: linux-2.6.13/include/asm-i386/mach-xen/hypervisor_hooks.h ==================================================================--- linux-2.6.13.orig/include/asm-i386/mach-xen/hypervisor_hooks.h 2005-08-08 21:12:55.000000000 -0700 +++ linux-2.6.13/include/asm-i386/mach-xen/hypervisor_hooks.h 2005-08-08 21:13:19.000000000 -0700 @@ -0,0 +1,27 @@ +#ifndef __ASM_HYPERVISOR_HOOKS_H +#define __ASM_HYPERVISOR_HOOKS_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_HYPERVISOR_HOOKS_H */