source: mainline/kernel/generic/src/mm/page.c@ 95658c9

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 95658c9 was 5a5269d, checked in by GitHub <noreply@…>, 6 years ago

Change type of uspace pointers in kernel from pointer type to numeric (#170)

From kernel's perspective, userspace addresses are not valid pointers,
and can only be used in calls to copy_to/from_uspace().
Therefore, we change the type of those arguments and variables to
uspace_addr_t which is an alias for sysarg_t.

This allows the compiler to catch accidental direct accesses to
userspace addresses.

Additionally, to avoid losing the type information in code,
a macro uspace_ptr(type) is used that translates to uspace_addr_t.
I makes no functional difference, but allows keeping the type information
in code in case we implement some sort of static checking for it in the future.

However, ccheck doesn't like that, so instead of using uspace_ptr(char),
we use uspace_ptr_char which is defined as
#define uspace_ptr_char uspace_ptr(char).

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2001-2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_generic_mm
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Virtual Address Translation subsystem.
36 *
37 * This file contains code for creating, destroying and searching
38 * mappings between virtual addresses and physical addresses.
39 * Functions here are mere wrappers that call the real implementation.
40 * They however, define the single interface.
41 *
42 */
43
44/*
45 * Note on memory prefetching and updating memory mappings, also described in:
46 * AMD x86-64 Architecture Programmer's Manual, Volume 2, System Programming,
47 * 7.2.1 Special Coherency Considerations.
48 *
49 * The processor which modifies a page table mapping can access prefetched data
50 * from the old mapping. In order to prevent this, we place a memory barrier
51 * after a mapping is updated.
52 *
53 * We assume that the other processors are either not using the mapping yet
54 * (i.e. during the bootstrap) or are executing the TLB shootdown code. While
55 * we don't care much about the former case, the processors in the latter case
56 * will do an implicit serialization by virtue of running the TLB shootdown
57 * interrupt handler.
58 *
59 */
60
61#include <mm/page.h>
62#include <genarch/mm/page_ht.h>
63#include <genarch/mm/page_pt.h>
64#include <arch/mm/page.h>
65#include <arch/mm/asid.h>
66#include <mm/as.h>
67#include <mm/frame.h>
68#include <barrier.h>
69#include <typedefs.h>
70#include <arch/asm.h>
71#include <arch.h>
72#include <assert.h>
73#include <syscall/copy.h>
74#include <errno.h>
75#include <align.h>
76
77/** Virtual operations for page subsystem. */
78page_mapping_operations_t *page_mapping_operations = NULL;
79
80void page_init(void)
81{
82 page_arch_init();
83}
84
85/** Insert mapping of page to frame.
86 *
87 * Map virtual address page to physical address frame
88 * using flags. Allocate and setup any missing page tables.
89 *
90 * @param as Address space to which page belongs.
91 * @param page Virtual address of the page to be mapped.
92 * @param frame Physical address of memory frame to which the mapping is
93 * done.
94 * @param flags Flags to be used for mapping.
95 *
96 */
97_NO_TRACE void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
98 unsigned int flags)
99{
100 assert(page_table_locked(as));
101
102 assert(page_mapping_operations);
103 assert(page_mapping_operations->mapping_insert);
104
105 page_mapping_operations->mapping_insert(as, ALIGN_DOWN(page, PAGE_SIZE),
106 ALIGN_DOWN(frame, FRAME_SIZE), flags);
107
108 /* Repel prefetched accesses to the old mapping. */
109 memory_barrier();
110}
111
112/** Remove mapping of page.
113 *
114 * Remove any mapping of page within address space as.
115 * TLB shootdown should follow in order to make effects of
116 * this call visible.
117 *
118 * @param as Address space to which page belongs.
119 * @param page Virtual address of the page to be demapped.
120 *
121 */
122_NO_TRACE void page_mapping_remove(as_t *as, uintptr_t page)
123{
124 assert(page_table_locked(as));
125
126 assert(page_mapping_operations);
127 assert(page_mapping_operations->mapping_remove);
128
129 page_mapping_operations->mapping_remove(as,
130 ALIGN_DOWN(page, PAGE_SIZE));
131
132 /* Repel prefetched accesses to the old mapping. */
133 memory_barrier();
134}
135
136/** Find mapping for virtual page.
137 *
138 * @param as Address space to which page belongs.
139 * @param page Virtual page.
140 * @param nolock True if the page tables need not be locked.
141 * @param[out] pte Structure that will receive a copy of the found PTE.
142 *
143 * @return True if a valid PTE is returned, false otherwise. Note that
144 * the PTE is not guaranteed to be present.
145 */
146_NO_TRACE bool page_mapping_find(as_t *as, uintptr_t page, bool nolock,
147 pte_t *pte)
148{
149 assert(nolock || page_table_locked(as));
150
151 assert(page_mapping_operations);
152 assert(page_mapping_operations->mapping_find);
153
154 return page_mapping_operations->mapping_find(as,
155 ALIGN_DOWN(page, PAGE_SIZE), nolock, pte);
156}
157
158/** Update mapping for virtual page.
159 *
160 * Use only to update accessed and modified/dirty bits.
161 *
162 * @param as Address space to which page belongs.
163 * @param page Virtual page.
164 * @param nolock True if the page tables need not be locked.
165 * @param pte New PTE.
166 */
167_NO_TRACE void page_mapping_update(as_t *as, uintptr_t page, bool nolock,
168 pte_t *pte)
169{
170 assert(nolock || page_table_locked(as));
171
172 assert(page_mapping_operations);
173 assert(page_mapping_operations->mapping_find);
174
175 page_mapping_operations->mapping_update(as,
176 ALIGN_DOWN(page, PAGE_SIZE), nolock, pte);
177}
178
179/** Make the mapping shared by all page tables (not address spaces).
180 *
181 * @param base Starting virtual address of the range that is made global.
182 * @param size Size of the address range that is made global.
183 */
184void page_mapping_make_global(uintptr_t base, size_t size)
185{
186 assert(page_mapping_operations);
187 assert(page_mapping_operations->mapping_make_global);
188
189 return page_mapping_operations->mapping_make_global(base, size);
190}
191
192errno_t page_find_mapping(uintptr_t virt, uintptr_t *phys)
193{
194 page_table_lock(AS, true);
195
196 pte_t pte;
197 bool found = page_mapping_find(AS, virt, false, &pte);
198 if (!found || !PTE_VALID(&pte) || !PTE_PRESENT(&pte)) {
199 page_table_unlock(AS, true);
200 return ENOENT;
201 }
202
203 *phys = PTE_GET_FRAME(&pte) +
204 (virt - ALIGN_DOWN(virt, PAGE_SIZE));
205
206 page_table_unlock(AS, true);
207
208 return EOK;
209}
210
211/** Syscall wrapper for getting mapping of a virtual page.
212 *
213 * @return EOK on success.
214 * @return ENOENT if no virtual address mapping found.
215 *
216 */
217sys_errno_t sys_page_find_mapping(uintptr_t virt, uspace_ptr_uintptr_t phys_ptr)
218{
219 uintptr_t phys;
220 errno_t rc = page_find_mapping(virt, &phys);
221 if (rc != EOK)
222 return rc;
223
224 rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
225 return (sys_errno_t) rc;
226}
227
228/** @}
229 */
Note: See TracBrowser for help on using the repository browser.