From d85fc52b409dc4007ab848388c3e096eec85268d Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Mon, 25 Jun 2012 09:25:25 +0200 Subject: control page: use vm_insert_page() instead of remap_pfn_range() vm_insert_page() is the simpler and preferred interface for remapping individual pages and includes additional error checks. It suffices for our purposes, so let's use it instead. --- litmus/ctrldev.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'litmus/ctrldev.c') diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c index 6677a67cc945..294d134a4a6d 100644 --- a/litmus/ctrldev.c +++ b/litmus/ctrldev.c @@ -30,27 +30,19 @@ static int alloc_ctrl_page(struct task_struct *t) static int map_ctrl_page(struct task_struct *t, struct vm_area_struct* vma) { int err; - unsigned long pfn; struct page* ctrl = virt_to_page(tsk_rt(t)->ctrl_page); - /* Increase ref count. Is decreased when vma is destroyed. */ - get_page(ctrl); - - /* compute page frame number */ - pfn = page_to_pfn(ctrl); - TRACE_CUR(CTRL_NAME - ": mapping %p (pfn:%lx, %lx) to 0x%lx (prot:%lx)\n", - tsk_rt(t)->ctrl_page, pfn, page_to_pfn(ctrl), vma->vm_start, + ": mapping %p (pfn:%lx) to 0x%lx (prot:%lx)\n", + tsk_rt(t)->ctrl_page,page_to_pfn(ctrl), vma->vm_start, vma->vm_page_prot); - /* Map it into the vma. Make sure to use PAGE_SHARED, otherwise - * userspace actually gets a copy-on-write page. */ - err = remap_pfn_range(vma, vma->vm_start, pfn, PAGE_SIZE, PAGE_SHARED); + /* Map it into the vma. */ + err = vm_insert_page(vma, vma->vm_start, ctrl); if (err) - TRACE_CUR(CTRL_NAME ": remap_pfn_range() failed (%d)\n", err); + TRACE_CUR(CTRL_NAME ": vm_insert_page() failed (%d)\n", err); return err; } -- cgit v1.2.2 From c85e6eae1698cecb15d63e112e937f706280c78e Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Mon, 25 Jun 2012 15:26:06 +0200 Subject: control page: warn on page fault Page faults should not happen here. Scream if they do anyway. This is useful when extending the control page. --- litmus/ctrldev.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'litmus/ctrldev.c') diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c index 294d134a4a6d..ec0fc4b1ab55 100644 --- a/litmus/ctrldev.c +++ b/litmus/ctrldev.c @@ -55,19 +55,19 @@ static void litmus_ctrl_vm_close(struct vm_area_struct* vma) TRACE_CUR(CTRL_NAME ": %p:%p vma:%p vma->vm_private_data:%p closed.\n", (void*) vma->vm_start, (void*) vma->vm_end, vma, - vma->vm_private_data, current->comm, - current->pid); + vma->vm_private_data); } static int litmus_ctrl_vm_fault(struct vm_area_struct* vma, struct vm_fault* vmf) { - /* This function should never be called, since - * all pages should have been mapped by mmap() - * already. */ - TRACE_CUR("%s flags=0x%x\n", __FUNCTION__, vma->vm_flags); + TRACE_CUR("%s flags=0x%x (off:%ld)\n", __FUNCTION__, + vma->vm_flags, vmf->pgoff); + + /* This function should never be called, since all pages should have + * been mapped by mmap() already. */ + WARN_ONCE(1, "Page faults should be impossible in the control page\n"); - /* nope, you only get one page */ return VM_FAULT_SIGBUS; } -- cgit v1.2.2 From a6d64b9717782170ba27c16b6df8191169d92fad Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Mon, 25 Jun 2012 15:29:17 +0200 Subject: control page: avoid "minor" page faults By default, even private writable pages are mapped with the RW bit disabled in the PTE. This causes a "minor" page fault when the page is first written to. To avoid this, make sure that vm_inert_page() uses the proper page protection bits and mark the VMA as VM_IO to keep the rest of the VM code out. --- litmus/ctrldev.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'litmus/ctrldev.c') diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c index ec0fc4b1ab55..9969ab17c190 100644 --- a/litmus/ctrldev.c +++ b/litmus/ctrldev.c @@ -95,9 +95,16 @@ static int litmus_ctrl_mmap(struct file* filp, struct vm_area_struct* vma) return -EINVAL; vma->vm_ops = &litmus_ctrl_vm_ops; - /* this mapping should not be kept across forks, - * and cannot be expanded */ - vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; + /* This mapping should not be kept across forks, + * cannot be expanded, and is not a "normal" page. */ + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_IO; + + /* We don't want the first write access to trigger a "minor" page fault + * to mark the page as dirty. This is transient, private memory, we + * don't care if it was touched or not. __S011 means RW access, but not + * execute, and avoids copy-on-write behavior. + * See protection_map in mmap.c. */ + vma->vm_page_prot = __S011; err = alloc_ctrl_page(current); if (!err) -- cgit v1.2.2