source: mainline/kernel/arch/mips32/src/mm/frame.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: 7.7 KB
Line 
1/*
2 * Copyright (c) 2005 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 mips32mm
30 * @{
31 */
32/** @file
33 */
34
35#include <macros.h>
36#include <arch/mm/frame.h>
37#include <arch/mm/tlb.h>
38#include <interrupt.h>
39#include <mm/frame.h>
40#include <mm/asid.h>
41#include <config.h>
42#ifdef MACHINE_msim
43#include <arch/drivers/msim.h>
44#endif
45#include <arch/arch.h>
46#include <print.h>
47
48#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K
49#define ZERO_FRAMES 2048
50#define ZERO_PAGE_WIDTH 18 /* 256K */
51#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH)
52#define ZERO_PAGE_ASID ASID_INVALID
53#define ZERO_PAGE_TLBI 0
54#define ZERO_PAGE_ADDR 0
55#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
56#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
57
58#define ZERO_PAGE_VALUE_KSEG1(frame) \
59 (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
60
61#define MAX_REGIONS 32
62
63typedef struct {
64 pfn_t start;
65 pfn_t count;
66} phys_region_t;
67
68static size_t phys_regions_count = 0;
69static phys_region_t phys_regions[MAX_REGIONS];
70
71/** Check whether frame is available
72 *
73 * Returns true if given frame is generally available for use.
74 * Returns false if given frame is used for physical memory
75 * mapped devices and cannot be used.
76 *
77 */
78static bool frame_available(pfn_t frame)
79{
80#ifdef MACHINE_msim
81 /* MSIM device (dprinter) */
82 if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
83 return false;
84
85 /* MSIM device (dkeyboard) */
86 if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
87 return false;
88#endif
89
90#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
91 if (frame >= (sdram_size >> ZERO_PAGE_WIDTH))
92 return false;
93#endif
94
95 return true;
96}
97
98
99/** Check whether frame is safe to write
100 *
101 * Returns true if given frame is safe for read/write test.
102 * Returns false if given frame should not be touched.
103 *
104 */
105static bool frame_safe(pfn_t frame)
106{
107 /* Kernel structures */
108 if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
109 return false;
110
111 /* Kernel */
112 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
113 KA2PA(config.base), config.kernel_size))
114 return false;
115
116 /* Kernel stack */
117 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
118 KA2PA(config.stack_base), config.stack_size))
119 return false;
120
121 /* Init tasks */
122 bool safe = true;
123 size_t i;
124 for (i = 0; i < init.cnt; i++)
125 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
126 init.tasks[i].paddr, init.tasks[i].size)) {
127 safe = false;
128 break;
129 }
130
131 return safe;
132}
133
134static void frame_add_region(pfn_t start_frame, pfn_t end_frame, bool low)
135{
136 if (end_frame <= start_frame)
137 return;
138
139 uintptr_t base = start_frame << ZERO_PAGE_WIDTH;
140 size_t size = (end_frame - start_frame) << ZERO_PAGE_WIDTH;
141
142 if (!frame_adjust_zone_bounds(low, &base, &size))
143 return;
144
145 pfn_t first = ADDR2PFN(base);
146 size_t count = SIZE2FRAMES(size);
147 pfn_t conf_frame;
148
149 if (low) {
150 /* Interrupt vector frame is blacklisted */
151 if (first == 0)
152 conf_frame = 1;
153 else
154 conf_frame = first;
155 zone_create(first, count, conf_frame,
156 ZONE_AVAILABLE | ZONE_LOWMEM);
157 } else {
158 conf_frame = zone_external_conf_alloc(count);
159 if (conf_frame != 0)
160 zone_create(first, count, conf_frame,
161 ZONE_AVAILABLE | ZONE_HIGHMEM);
162 }
163
164 if (phys_regions_count < MAX_REGIONS) {
165 phys_regions[phys_regions_count].start = first;
166 phys_regions[phys_regions_count].count = count;
167 phys_regions_count++;
168 }
169}
170
171
172/** Create memory zones
173 *
174 * Walk through available 256 KB chunks of physical
175 * memory and create zones.
176 *
177 * Note: It is assumed that the TLB is not yet being
178 * used in any way, thus there is no interference.
179 *
180 */
181void frame_low_arch_init(void)
182{
183 ipl_t ipl = interrupts_disable();
184
185 /* Clear and initialize TLB */
186 cp0_pagemask_write(ZERO_PAGE_MASK);
187 cp0_entry_lo0_write(0);
188 cp0_entry_lo1_write(0);
189 cp0_entry_hi_write(0);
190
191 size_t i;
192 for (i = 0; i < TLB_ENTRY_COUNT; i++) {
193 cp0_index_write(i);
194 tlbwi();
195 }
196
197 pfn_t start_frame = 0;
198 pfn_t frame;
199 bool avail = true;
200
201 /* Walk through all 1 MB frames */
202 for (frame = 0; frame < ZERO_FRAMES; frame++) {
203 if (!frame_available(frame))
204 avail = false;
205 else {
206 if (frame_safe(frame)) {
207 entry_lo_t lo0;
208 entry_lo_t lo1;
209 entry_hi_t hi;
210 tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
211 tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
212 tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
213
214 cp0_pagemask_write(ZERO_PAGE_MASK);
215 cp0_entry_lo0_write(lo0.value);
216 cp0_entry_lo1_write(lo1.value);
217 cp0_entry_hi_write(hi.value);
218 cp0_index_write(ZERO_PAGE_TLBI);
219 tlbwi();
220
221 ZERO_PAGE_VALUE = 0;
222 if (ZERO_PAGE_VALUE != 0)
223 avail = false;
224 else {
225 ZERO_PAGE_VALUE = 0xdeadbeef;
226 if (ZERO_PAGE_VALUE != 0xdeadbeef)
227 avail = false;
228 }
229 }
230 }
231
232 if (!avail) {
233 frame_add_region(start_frame, frame, true);
234 start_frame = frame + 1;
235 avail = true;
236 }
237 }
238
239 frame_add_region(start_frame, frame, true);
240
241 /* Blacklist interrupt vector frame */
242 frame_mark_unavailable(0, 1);
243
244#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
245 /* Blacklist memory regions used by YAMON.
246 *
247 * The YAMON User's Manual vaguely says the following physical addresses
248 * are taken by YAMON:
249 *
250 * 0x1000 YAMON functions
251 * 0x5000 YAMON code
252 *
253 * These addresses overlap with the beginning of the SDRAM so we need to
254 * make sure they cannot be allocated.
255 *
256 * The User's Manual unfortunately does not say where does the SDRAM
257 * portion used by YAMON end.
258 *
259 * Looking into the YAMON 02.21 sources, it looks like the first free
260 * address is computed dynamically and depends on the size of the YAMON
261 * image. From the YAMON binary, it appears to be 0xc0d50 or roughly
262 * 772 KiB for that particular version.
263 *
264 * Linux is linked to 1MiB which seems to be a safe bet and a reasonable
265 * upper bound for memory taken by YAMON. We will use it too.
266 */
267 frame_mark_unavailable(0, 1024 * 1024 / FRAME_SIZE);
268#endif
269
270 /* Cleanup */
271 cp0_pagemask_write(ZERO_PAGE_MASK);
272 cp0_entry_lo0_write(0);
273 cp0_entry_lo1_write(0);
274 cp0_entry_hi_write(0);
275 cp0_index_write(ZERO_PAGE_TLBI);
276 tlbwi();
277
278 interrupts_restore(ipl);
279}
280
281void frame_high_arch_init(void)
282{
283}
284
285void physmem_print(void)
286{
287 printf("[base ] [size ]\n");
288
289 size_t i;
290 for (i = 0; i < phys_regions_count; i++) {
291 printf("%#010x %10u\n",
292 PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
293 }
294}
295
296/** @}
297 */
Note: See TracBrowser for help on using the repository browser.