source: mainline/kernel/generic/src/mm/backend_anon.c@ 4bb31f7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4bb31f7 was 2057572, checked in by Jakub Jermar <jakub@…>, 18 years ago

The Ultimate Solution To Illegal Virtual Aliases.
It is better to avoid them completely than to fight them.
Switch the sparc64 port to 16K pages. The TLBs and TSBs
continue to operate with 8K pages only. Page tables and
other generic parts operate with 16K pages.

Because the MMU doesn't support 16K directly, each 16K
page is emulated by a pair of 8K pages. With 16K pages,
illegal aliases cannot be created in 16K D-cache.

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 * Copyright (c) 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 Backend for anonymous memory address space areas.
36 *
37 */
38
39#include <mm/as.h>
40#include <mm/page.h>
41#include <genarch/mm/page_pt.h>
42#include <genarch/mm/page_ht.h>
43#include <mm/frame.h>
44#include <mm/slab.h>
45#include <synch/mutex.h>
46#include <adt/list.h>
47#include <adt/btree.h>
48#include <errno.h>
49#include <arch/types.h>
50#include <align.h>
51#include <arch.h>
52
53#ifdef CONFIG_VIRT_IDX_DCACHE
54#include <arch/mm/cache.h>
55#endif
56
57static int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
58static void anon_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
59static void anon_share(as_area_t *area);
60
61mem_backend_t anon_backend = {
62 .page_fault = anon_page_fault,
63 .frame_free = anon_frame_free,
64 .share = anon_share
65};
66
67/** Service a page fault in the anonymous memory address space area.
68 *
69 * The address space area and page tables must be already locked.
70 *
71 * @param area Pointer to the address space area.
72 * @param addr Faulting virtual address.
73 * @param access Access mode that caused the fault (i.e. read/write/exec).
74 *
75 * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e.
76 * serviced).
77 */
78int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
79{
80 uintptr_t frame;
81 bool dirty = false;
82
83 if (!as_area_check_access(area, access))
84 return AS_PF_FAULT;
85
86 if (area->sh_info) {
87 btree_node_t *leaf;
88
89 /*
90 * The area is shared, chances are that the mapping can be found
91 * in the pagemap of the address space area share info
92 * structure.
93 * In the case that the pagemap does not contain the respective
94 * mapping, a new frame is allocated and the mapping is created.
95 */
96 mutex_lock(&area->sh_info->lock);
97 frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
98 ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
99 if (!frame) {
100 bool allocate = true;
101 int i;
102
103 /*
104 * Zero can be returned as a valid frame address.
105 * Just a small workaround.
106 */
107 for (i = 0; i < leaf->keys; i++) {
108 if (leaf->key[i] ==
109 ALIGN_DOWN(addr, PAGE_SIZE)) {
110 allocate = false;
111 break;
112 }
113 }
114 if (allocate) {
115 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
116 memsetb(PA2KA(frame), FRAME_SIZE, 0);
117 dirty = true;
118
119 /*
120 * Insert the address of the newly allocated
121 * frame to the pagemap.
122 */
123 btree_insert(&area->sh_info->pagemap,
124 ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
125 (void *) frame, leaf);
126 }
127 }
128 frame_reference_add(ADDR2PFN(frame));
129 mutex_unlock(&area->sh_info->lock);
130 } else {
131
132 /*
133 * In general, there can be several reasons that
134 * can have caused this fault.
135 *
136 * - non-existent mapping: the area is an anonymous
137 * area (e.g. heap or stack) and so far has not been
138 * allocated a frame for the faulting page
139 *
140 * - non-present mapping: another possibility,
141 * currently not implemented, would be frame
142 * reuse; when this becomes a possibility,
143 * do not forget to distinguish between
144 * the different causes
145 */
146 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
147 memsetb(PA2KA(frame), FRAME_SIZE, 0);
148 dirty = true;
149 }
150
151 /*
152 * Map 'page' to 'frame'.
153 * Note that TLB shootdown is not attempted as only new information is
154 * being inserted into page tables.
155 */
156 page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
157 if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
158 panic("Could not insert used space.\n");
159
160 return AS_PF_OK;
161}
162
163/** Free a frame that is backed by the anonymous memory backend.
164 *
165 * The address space area and page tables must be already locked.
166 *
167 * @param area Ignored.
168 * @param page Virtual address of the page corresponding to the frame.
169 * @param frame Frame to be released.
170 */
171void anon_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
172{
173 frame_free(frame);
174}
175
176/** Share the anonymous address space area.
177 *
178 * Sharing of anonymous area is done by duplicating its entire mapping
179 * to the pagemap. Page faults will primarily search for frames there.
180 *
181 * The address space and address space area must be already locked.
182 *
183 * @param area Address space area to be shared.
184 */
185void anon_share(as_area_t *area)
186{
187 link_t *cur;
188
189 /*
190 * Copy used portions of the area to sh_info's page map.
191 */
192 mutex_lock(&area->sh_info->lock);
193 for (cur = area->used_space.leaf_head.next;
194 cur != &area->used_space.leaf_head; cur = cur->next) {
195 btree_node_t *node;
196 int i;
197
198 node = list_get_instance(cur, btree_node_t, leaf_link);
199 for (i = 0; i < node->keys; i++) {
200 uintptr_t base = node->key[i];
201 count_t count = (count_t) node->value[i];
202 int j;
203
204 for (j = 0; j < count; j++) {
205 pte_t *pte;
206
207 page_table_lock(area->as, false);
208 pte = page_mapping_find(area->as,
209 base + j * PAGE_SIZE);
210 ASSERT(pte && PTE_VALID(pte) &&
211 PTE_PRESENT(pte));
212 btree_insert(&area->sh_info->pagemap,
213 (base + j * PAGE_SIZE) - area->base,
214 (void *) PTE_GET_FRAME(pte), NULL);
215 page_table_unlock(area->as, false);
216
217 pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
218 frame_reference_add(pfn);
219 }
220
221 }
222 }
223 mutex_unlock(&area->sh_info->lock);
224}
225
226/** @}
227 */
Note: See TracBrowser for help on using the repository browser.