Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 113229
b: refs/heads/master
c: a403e45
h: refs/heads/master
i:
  113227: 9054da4
v: v3
  • Loading branch information
Ingo Molnar committed Jul 28, 2008
1 parent 4cac549 commit 5eee86a
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d974ae379a2fbe8948f01eabbc6b19c0a80f09bc
refs/heads/master: a403e45c3b678211ee3b7225dbb924921fb5ddd3
9 changes: 8 additions & 1 deletion trunk/arch/x86/kernel/ldt.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
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();
Expand All @@ -75,6 +77,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
#endif
}
if (oldsize) {
paravirt_free_ldt(oldldt, oldsize);
if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
vfree(oldldt);
else
Expand All @@ -86,10 +89,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
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;
}

Expand Down Expand Up @@ -126,6 +132,7 @@ void destroy_context(struct mm_struct *mm)
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
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/x86/kernel/paravirt.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ struct pv_cpu_ops pv_cpu_ops = {
.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)
Expand Down
60 changes: 57 additions & 3 deletions trunk/arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,57 @@ static unsigned long xen_store_tr(void)
return 0;
}

/*
* If 'v' is a vmalloc mapping, then find the linear mapping of the
* page (if any) and also set its protections to match:
*/
static void set_aliased_prot(void *v, pgprot_t prot)
{
int level;
pte_t *ptep;
pte_t pte;
unsigned long pfn;
struct page *page;

ptep = lookup_address((unsigned long)v, &level);
BUG_ON(ptep == NULL);

pfn = pte_pfn(*ptep);
page = pfn_to_page(pfn);

pte = pfn_pte(pfn, prot);

if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
BUG();

if (!PageHighMem(page)) {
void *av = __va(PFN_PHYS(pfn));

if (av != v)
if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0))
BUG();
} else
kmap_flush_unused();
}

static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
{
const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
int i;

for(i = 0; i < entries; i += entries_per_page)
set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
}

static void xen_free_ldt(struct desc_struct *ldt, unsigned entries)
{
const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
int i;

for(i = 0; i < entries; i += entries_per_page)
set_aliased_prot(ldt + i, PAGE_KERNEL);
}

static void xen_set_ldt(const void *addr, unsigned entries)
{
struct mmuext_op *op;
Expand Down Expand Up @@ -426,7 +477,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
const void *ptr)
{
unsigned long lp = (unsigned long)&dt[entrynum];
xmaddr_t mach_lp = virt_to_machine(lp);
xmaddr_t mach_lp = arbitrary_virt_to_machine(lp);
u64 entry = *(u64 *)ptr;

preempt_disable();
Expand Down Expand Up @@ -559,7 +610,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
}

static void xen_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
struct thread_struct *thread)
{
struct multicall_space mcs = xen_mc_entry(0);
MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
Expand Down Expand Up @@ -1220,6 +1271,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
.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,
Expand Down Expand Up @@ -1324,7 +1378,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
.ptep_modify_prot_commit = __ptep_modify_prot_commit,

.pte_val = xen_pte_val,
.pte_flags = native_pte_val,
.pte_flags = native_pte_flags,
.pgd_val = xen_pgd_val,

.make_pte = xen_make_pte,
Expand Down
15 changes: 14 additions & 1 deletion trunk/include/asm-x86/desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ static inline void fill_ldt(struct desc_struct *desc,
desc->d = info->seg_32bit;
desc->g = info->limit_in_pages;
desc->base2 = (info->base_addr & 0xff000000) >> 24;
/*
* Don't allow setting of the lm bit. It is useless anyway
* because 64bit system calls require __USER_CS:
*/
desc->l = 0;
}

extern struct desc_ptr idt_descr;
Expand Down Expand Up @@ -97,7 +102,15 @@ static inline int desc_empty(const void *ptr)
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)
Expand Down
13 changes: 13 additions & 0 deletions trunk/include/asm-x86/paravirt.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ struct pv_cpu_ops {
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);
Expand Down Expand Up @@ -824,6 +827,16 @@ do { \
(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);
Expand Down

0 comments on commit 5eee86a

Please sign in to comment.