|
|
1.1 root 1: /*
2: * Creation Date: <1999/11/07 19:02:11 samuel>
3: * Time-stamp: <2004/01/07 19:42:36 samuel>
4: *
5: * <ofmem.c>
6: *
7: * OF Memory manager
8: *
9: * Copyright (C) 1999-2004 Samuel Rydh ([email protected])
10: * Copyright (C) 2004 Stefan Reinauer
11: *
12: * This program is free software; you can redistribute it and/or
13: * modify it under the terms of the GNU General Public License
14: * as published by the Free Software Foundation
15: *
16: */
17:
18: /* TODO: Clean up MOLisms in a decent way */
19:
20: #include "config.h"
21: #include "libopenbios/bindings.h"
22: #include "libc/string.h"
23: #include "libopenbios/ofmem.h"
24: #include "kernel.h"
25: #ifdef I_WANT_MOLISMS
26: #include "mol/prom.h"
27: #include "mol/mol.h"
28: #endif
29: #include "mmutypes.h"
30: #include "asm/processor.h"
31: #ifdef I_WANT_MOLISMS
32: #include "osi_calls.h"
33: #endif
34:
35: #define BIT(n) (1U<<(31-(n)))
36:
37: /* called from assembly */
38: extern void dsi_exception( void );
39: extern void isi_exception( void );
40: extern void setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize );
41:
42: /****************************************************************
43: * Memory usage (before of_quiesce is called)
44: *
45: * Physical
46: *
47: * 0x00000000 Exception vectors
48: * 0x00004000 Free space
49: * 0x01e00000 Open Firmware (us)
50: * 0x01f00000 OF allocations
51: * 0x01ff0000 PTE Hash
52: * 0x02000000- Free space
53: *
54: * Allocations grow downwards from 0x01e00000
55: *
56: ****************************************************************/
57:
58: #define HASH_SIZE (2 << 15)
59: #define SEGR_BASE 0x400 /* segment number range to use */
60:
61: #define FREE_BASE_1 0x00004000
62: #define OF_CODE_START 0x01e00000
63: /* #define OF_MALLOC_BASE 0x01f00000 */
64: extern char _end[];
65: #define OF_MALLOC_BASE _end
66:
67: #define HASH_BASE (0x02000000 - HASH_SIZE)
68: #define FREE_BASE_2 0x02000000
69:
70: #define RAMSIZE 0x02000000 /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */
71:
72: static ofmem_t s_ofmem;
73:
74: #define IO_BASE 0x80000000
75: #define OFMEM (&s_ofmem)
76:
77: static inline unsigned long
78: get_hash_base( void )
79: {
80: return HASH_BASE;
81: }
82:
83: static inline unsigned long
84: get_hash_size( void )
85: {
86: return HASH_SIZE;
87: }
88:
89: static ucell get_heap_top( void )
90: {
91: return HASH_BASE;
92: }
93:
94: static inline size_t ALIGN_SIZE(size_t x, size_t a)
95: {
96: return (x + a - 1) & ~(a-1);
97: }
98:
99: ofmem_t* ofmem_arch_get_private(void)
100: {
101: return OFMEM;
102: }
103:
104: void* ofmem_arch_get_malloc_base(void)
105: {
106: return OF_MALLOC_BASE;
107: }
108:
109: ucell ofmem_arch_get_heap_top(void)
110: {
111: return get_heap_top();
112: }
113:
114: ucell ofmem_arch_get_virt_top(void)
115: {
116: return IO_BASE;
117: }
118:
119: void ofmem_arch_unmap_pages(ucell virt, ucell size)
120: {
121: /* kill page mappings in provided range */
122: }
123:
1.1.1.2 ! root 124: void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode)
1.1 root 125: {
126: /* none yet */
127: }
128:
129: /************************************************************************/
130: /* OF private allocations */
131: /************************************************************************/
132:
133: void *
134: malloc( int size )
135: {
136: return ofmem_malloc(size);
137: }
138:
139: void
140: free( void *ptr )
141: {
142: return ofmem_free(ptr);
143: }
144:
145: void *
146: realloc( void *ptr, size_t size )
147: {
148: return ofmem_realloc(ptr, size);
149: }
150:
151:
152: /************************************************************************/
153: /* misc */
154: /************************************************************************/
155:
156: ucell ofmem_arch_default_translation_mode( ucell phys )
157: {
158: /* XXX: Guard bit not set as it should! */
159: if( phys < IO_BASE || phys >= 0xffc00000 )
160: return 0x02; /*0xa*/ /* wim GxPp */
161: return 0x6a; /* WIm GxPp, I/O */
162: }
163:
164:
165: /************************************************************************/
166: /* page fault handler */
167: /************************************************************************/
168:
169: static ucell
170: ea_to_phys( ucell ea, ucell *mode )
171: {
172: ucell phys;
173:
174: /* hardcode our translation needs */
175: if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) {
176: *mode = ofmem_arch_default_translation_mode( ea );
177: return ea;
178: }
179:
180: phys = ofmem_translate(ea, mode);
181: if( phys == (ucell)-1 ) {
182: #ifdef I_WANT_MOLISMS
183: if( ea != 0x80816c00 )
184: printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea );
185: #endif
186: phys = ea;
187: *mode = ofmem_arch_default_translation_mode( phys );
188:
189: #ifdef I_WANT_MOLISMS
190: forth_segv_handler( (char*)ea );
191: OSI_Debugger(1);
192: #endif
193: /* print_virt_range(); */
194: /* print_phys_range(); */
195: /* print_trans(); */
196: }
197: return phys;
198: }
199:
200: static void
201: hash_page( ucell ea, ucell phys, ucell mode )
202: {
203: static int next_grab_slot=0;
204: unsigned long *upte, cmp, hash1;
205: int i, vsid, found;
206: mPTE_t *pp;
207:
208: vsid = (ea>>28) + SEGR_BASE;
209: cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
210:
211: hash1 = vsid;
212: hash1 ^= (ea >> 12) & 0xffff;
213: hash1 &= (get_hash_size() - 1) >> 6;
214:
215: pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
216: upte = (unsigned long*)pp;
217:
218: /* replace old translation */
219: for( found=0, i=0; !found && i<8; i++ )
220: if( cmp == upte[i*2] )
221: found=1;
222:
223: /* otherwise use a free slot */
224: for( i=0; !found && i<8; i++ )
225: if( !pp[i].v )
226: found=1;
227:
228: /* out of slots, just evict one */
229: if( !found ) {
230: i = next_grab_slot + 1;
231: next_grab_slot = (next_grab_slot + 1) % 8;
232: }
233: i--;
234: upte[i*2] = cmp;
235: upte[i*2+1] = (phys & ~0xfff) | mode;
236:
237: asm volatile( "tlbie %0" :: "r"(ea) );
238: }
239:
240: void
241: dsi_exception( void )
242: {
243: unsigned long dar, dsisr;
244: ucell mode;
245: ucell phys;
246:
247: asm volatile("mfdar %0" : "=r" (dar) : );
248: asm volatile("mfdsisr %0" : "=r" (dsisr) : );
249:
250: //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
251:
252: phys = ea_to_phys(dar, &mode);
253: hash_page( dar, phys, mode );
254: }
255:
256: void
257: isi_exception( void )
258: {
259: unsigned long nip, srr1;
260: ucell mode;
261: ucell phys;
262:
263: asm volatile("mfsrr0 %0" : "=r" (nip) : );
264: asm volatile("mfsrr1 %0" : "=r" (srr1) : );
265:
266: //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
267:
268: phys = ea_to_phys(nip, &mode);
269: hash_page( nip, phys, mode );
270: }
271:
272:
273: /************************************************************************/
274: /* init / cleanup */
275: /************************************************************************/
276:
277: void
278: setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize )
279: {
280: unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16);
281: unsigned long sr_base = (0x20 << 24) | SEGR_BASE;
282: unsigned long msr;
283: int i;
284:
285: asm volatile("mtsdr1 %0" :: "r" (sdr1) );
286: for( i=0; i<16; i++ ) {
287: int j = i << 28;
288: asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) );
289: }
290: asm volatile("mfmsr %0" : "=r" (msr) : );
291: msr |= MSR_IR | MSR_DR;
292: asm volatile("mtmsr %0" :: "r" (msr) );
293: }
294:
295: void
296: ofmem_init( void )
297: {
298: ofmem_t *ofmem = OFMEM;
299: /* In case we can't rely on memory being zero initialized */
300: memset(ofmem, 0, sizeof(ofmem));
301:
302: ofmem->ramsize = RAMSIZE;
303:
304: ofmem_claim_phys( 0, FREE_BASE_1, 0 );
305: ofmem_claim_virt( 0, FREE_BASE_1, 0 );
306: ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
307: ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.