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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • 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 genericmm
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 <arch/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 */
97NO_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 */
122NO_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 */
146NO_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 */
167NO_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, 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.