source: mainline/kernel/arch/mips32/src/mm/frame.c@ 5f0f29ce

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5f0f29ce was 9962f53, checked in by Martin Decky <martin@…>, 16 years ago

remove typo

  • Property mode set to 100644
File size: 7.0 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#include <arch/drivers/msim.h>
43#include <arch/drivers/serial.h>
44#include <print.h>
45
46#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K
47#define ZERO_FRAMES 2048
48#define ZERO_PAGE_WIDTH 18 /* 256K */
49#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH)
50#define ZERO_PAGE_ASID ASID_INVALID
51#define ZERO_PAGE_TLBI 0
52#define ZERO_PAGE_ADDR 0
53#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
54#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
55
56#define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
57
58#define MAX_REGIONS 32
59
60typedef struct {
61 pfn_t start;
62 pfn_t count;
63} phys_region_t;
64
65static count_t phys_regions_count = 0;
66static phys_region_t phys_regions[MAX_REGIONS];
67
68uintptr_t end_frame = 0;
69
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#ifdef MACHINE_simics
91 /* Simics device (serial line) */
92 if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
93 return false;
94#endif
95
96#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
97 /* gxemul devices */
98 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
99 0x10000000, MB2SIZE(256)))
100 return false;
101#endif
102
103 return true;
104}
105
106
107/** Check whether frame is safe to write
108 *
109 * Returns true if given frame is safe for read/write test.
110 * Returns false if given frame should not be touched.
111 *
112 */
113static bool frame_safe(pfn_t frame)
114{
115 /* Kernel structures */
116 if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
117 return false;
118
119 /* Kernel */
120 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
121 KA2PA(config.base), config.kernel_size))
122 return false;
123
124 /* Kernel stack */
125 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
126 KA2PA(config.stack_base), config.stack_size))
127 return false;
128
129 /* Init tasks */
130 bool safe = true;
131 count_t i;
132 for (i = 0; i < init.cnt; i++)
133 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
134 KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
135 safe = false;
136 break;
137 }
138
139 return safe;
140}
141
142static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
143{
144 if (end_frame > start_frame) {
145 /* Convert 1M frames to 16K frames */
146 pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
147 pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
148
149 /* Interrupt vector frame is blacklisted */
150 pfn_t conf_frame;
151 if (first == 0)
152 conf_frame = 1;
153 else
154 conf_frame = first;
155
156 zone_create(first, count, conf_frame, 0);
157
158 if (phys_regions_count < MAX_REGIONS) {
159 phys_regions[phys_regions_count].start = first;
160 phys_regions[phys_regions_count].count = count;
161 phys_regions_count++;
162 }
163 }
164}
165
166
167/** Create memory zones
168 *
169 * Walk through available 256 KB chunks of physical
170 * memory and create zones.
171 *
172 * Note: It is assumed that the TLB is not yet being
173 * used in any way, thus there is no interference.
174 *
175 */
176void frame_arch_init(void)
177{
178 ipl_t ipl = interrupts_disable();
179
180 /* Clear and initialize TLB */
181 cp0_pagemask_write(ZERO_PAGE_MASK);
182 cp0_entry_lo0_write(0);
183 cp0_entry_lo1_write(0);
184 cp0_entry_hi_write(0);
185
186 count_t i;
187 for (i = 0; i < TLB_ENTRY_COUNT; i++) {
188 cp0_index_write(i);
189 tlbwi();
190 }
191
192 pfn_t start_frame = 0;
193 pfn_t frame;
194 bool avail = true;
195
196 /* Walk through all 1 MB frames */
197 for (frame = 0; frame < ZERO_FRAMES; frame++) {
198 if (!frame_available(frame))
199 avail = false;
200 else {
201 if (frame_safe(frame)) {
202 entry_lo_t lo0;
203 entry_lo_t lo1;
204 entry_hi_t hi;
205 tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
206 tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
207 tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
208
209 cp0_pagemask_write(ZERO_PAGE_MASK);
210 cp0_entry_lo0_write(lo0.value);
211 cp0_entry_lo1_write(lo1.value);
212 cp0_entry_hi_write(hi.value);
213 cp0_index_write(ZERO_PAGE_TLBI);
214 tlbwi();
215
216 ZERO_PAGE_VALUE = 0;
217 if (ZERO_PAGE_VALUE != 0)
218 avail = false;
219 else {
220 ZERO_PAGE_VALUE = 0xdeadbeef;
221 if (ZERO_PAGE_VALUE != 0xdeadbeef)
222 avail = false;
223#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
224 else {
225 ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
226 if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
227 avail = false;
228 }
229#endif
230 }
231 }
232 }
233
234 if (!avail) {
235 frame_add_region(start_frame, frame);
236 start_frame = frame + 1;
237 avail = true;
238 }
239 }
240
241 end_frame = frame;
242
243 frame_add_region(start_frame, end_frame);
244
245 /* Blacklist interrupt vector frame */
246 frame_mark_unavailable(0, 1);
247
248 /* Cleanup */
249 cp0_pagemask_write(ZERO_PAGE_MASK);
250 cp0_entry_lo0_write(0);
251 cp0_entry_lo1_write(0);
252 cp0_entry_hi_write(0);
253 cp0_index_write(ZERO_PAGE_TLBI);
254 tlbwi();
255
256 interrupts_restore(ipl);
257}
258
259
260void physmem_print(void)
261{
262 printf("Base Size\n");
263 printf("---------- ----------\n");
264
265 count_t i;
266 for (i = 0; i < phys_regions_count; i++) {
267 printf("%#010x %10u\n",
268 PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
269 }
270}
271
272/** @}
273 */
Note: See TracBrowser for help on using the repository browser.