Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 83194
b: refs/heads/master
c: 3963333
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Dike authored and Linus Torvalds committed Feb 5, 2008
1 parent be7df64 commit d4acc74
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 75 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: 42a2b54ce8c7b9d4f418995a7950e7e2e15e52ce
refs/heads/master: 3963333fe6767f15141ab2dc3b933721c636c212
19 changes: 4 additions & 15 deletions trunk/arch/um/include/as-layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,10 @@
#define _AC(X, Y) __AC(X, Y)
#endif

/*
* The "- 1"'s are to avoid gcc complaining about integer overflows
* and unrepresentable decimal constants. With 3-level page tables,
* TASK_SIZE is 0x80000000, which gets turned into its signed decimal
* equivalent in asm-offsets.s. gcc then complains about that being
* unsigned only in C90. To avoid that, UM_TASK_SIZE is defined as
* TASK_SIZE - 1. To compensate, we need to add the 1 back here.
* However, adding it back to UM_TASK_SIZE produces more gcc
* complaints. So, I adjust the thing being subtracted from
* UM_TASK_SIZE instead. Bah.
*/
#define STUB_CODE _AC((unsigned long), \
UM_TASK_SIZE - (2 * UM_KERN_PAGE_SIZE - 1))
#define STUB_DATA _AC((unsigned long), UM_TASK_SIZE - (UM_KERN_PAGE_SIZE - 1))
#define STUB_START _AC(, STUB_CODE)
#define STUB_START _AC(, 0x100000)
#define STUB_CODE _AC((unsigned long), STUB_START)
#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)

#ifndef __ASSEMBLY__

Expand Down
3 changes: 0 additions & 3 deletions trunk/arch/um/include/common-offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,3 @@ DEFINE(UM_HZ, HZ);
DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC);

/* See as-layout.h for an explanation of the "- 1". Bah. */
DEFINE(UM_TASK_SIZE, TASK_SIZE - 1);
5 changes: 3 additions & 2 deletions trunk/arch/um/kernel/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
void flush_thread(void)
{
void *data = NULL;
unsigned long end = proc_mm ? TASK_SIZE : STUB_START;
int ret;

arch_flush_thread(&current->thread.arch);

ret = unmap(&current->mm->context.id, 0, end, 1, &data);
ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
ret = ret || unmap(&current->mm->context.id, STUB_END,
TASK_SIZE - STUB_END, 1, &data);
if (ret) {
printk(KERN_ERR "flush_thread - clearing address space failed, "
"err = %d\n", ret);
Expand Down
104 changes: 59 additions & 45 deletions trunk/arch/um/kernel/skas/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,6 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;

/*
* There's an interaction between the skas0 stub pages, stack
* randomization, and the BUG at the end of exit_mmap. exit_mmap
* checks that the number of page tables freed is the same as had
* been allocated. If the stack is on the last page table page,
* then the stack pte page will be freed, and if not, it won't. To
* avoid having to know where the stack is, or if the process mapped
* something at the top of its address space for some other reason,
* we set TASK_SIZE to end at the start of the last page table.
* This keeps exit_mmap off the last page, but introduces a leak
* of that page. So, we hang onto it here and free it in
* destroy_context_skas.
*/

mm->context.last_page_table = pmd_page_vaddr(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif

*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
return 0;
Expand All @@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
stack = get_zeroed_page(GFP_KERNEL);
if (stack == 0)
goto out;

/*
* This zeros the entry that pgd_alloc didn't, needed since
* we are about to reinitialize it, and want mm.nr_ptes to
* be accurate.
*/
mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);

ret = init_stub_pte(mm, STUB_CODE,
(unsigned long) &__syscall_stub_start);
if (ret)
goto out_free;

ret = init_stub_pte(mm, STUB_DATA, stack);
if (ret)
goto out_free;

mm->nr_ptes--;
}

to_mm->id.stack = stack;
Expand Down Expand Up @@ -137,6 +100,64 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
return ret;
}

void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
{
struct page **pages;
int err, ret;

if (!skas_needs_stub)
return;

ret = init_stub_pte(mm, STUB_CODE,
(unsigned long) &__syscall_stub_start);
if (ret)
goto out;

ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
if (ret)
goto out;

pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
if (pages == NULL) {
printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
"pointers\n");
goto out;
}

pages[0] = virt_to_page(&__syscall_stub_start);
pages[1] = virt_to_page(mm->context.id.stack);

/* dup_mmap already holds mmap_sem */
err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
VM_READ | VM_MAYREAD | VM_EXEC |
VM_MAYEXEC | VM_DONTCOPY, pages);
if (err) {
printk(KERN_ERR "install_special_mapping returned %d\n", err);
goto out_free;
}
return;

out_free:
kfree(pages);
out:
force_sigsegv(SIGSEGV, current);
}

void arch_exit_mmap(struct mm_struct *mm)
{
pte_t *pte;

pte = virt_to_pte(mm, STUB_CODE);
if (pte != NULL)
pte_clear(mm, STUB_CODE, pte);

pte = virt_to_pte(mm, STUB_DATA);
if (pte == NULL)
return;

pte_clear(mm, STUB_DATA, pte);
}

void destroy_context(struct mm_struct *mm)
{
struct mm_context *mmu = &mm->context;
Expand All @@ -146,15 +167,8 @@ void destroy_context(struct mm_struct *mm)
else
os_kill_ptraced_process(mmu->id.u.pid, 1);

if (!proc_mm || !ptrace_faultinfo) {
if (skas_needs_stub)
free_page(mmu->id.stack);
pte_lock_deinit(virt_to_page(mmu->last_page_table));
pte_free_kernel(mm, (pte_t *) mmu->last_page_table);
dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
#ifdef CONFIG_3_LEVEL_PGTABLES
pmd_free(mm, (pmd_t *) mmu->last_pmd);
#endif
}

free_ldt(mmu);
}
11 changes: 4 additions & 7 deletions trunk/arch/um/kernel/tlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,

pte = pte_offset_kernel(pmd, addr);
do {
if ((addr >= STUB_START) && (addr < STUB_END))
continue;

r = pte_read(*pte);
w = pte_write(*pte);
x = pte_exec(*pte);
Expand Down Expand Up @@ -486,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
if (!proc_mm && (end_addr > STUB_START))
end_addr = STUB_START;

fix_range_common(mm, start_addr, end_addr, force);
}

Expand All @@ -502,17 +502,14 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,

void flush_tlb_mm(struct mm_struct *mm)
{
unsigned long end;

/*
* Don't bother flushing if this address space is about to be
* destroyed.
*/
if (atomic_read(&mm->mm_users) == 0)
return;

end = proc_mm ? TASK_SIZE : STUB_START;
fix_range(mm, 0, end, 0);
fix_range(mm, 0, TASK_SIZE, 0);
}

void force_flush_all(void)
Expand Down
7 changes: 5 additions & 2 deletions trunk/include/asm-um/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
#ifndef __UM_MMU_CONTEXT_H
#define __UM_MMU_CONTEXT_H

#include <asm-generic/mm_hooks.h>

#include "linux/sched.h"
#include "um_mmu.h"

extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
extern void arch_exit_mmap(struct mm_struct *mm);

#define get_mmu_context(task) do ; while(0)
#define activate_context(tsk) do ; while(0)

Expand All @@ -30,6 +31,8 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
*/
if (old != new && (current->flags & PF_BORROWED_MM))
__switch_mm(&new->context.id);

arch_dup_mmap(old, new);
}

static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
Expand Down

0 comments on commit d4acc74

Please sign in to comment.