2 * Creation Date: <1999/11/07 19:02:11 samuel>
3 * Time-stamp: <2004/01/07 19:42:36 samuel>
9 * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
10 * Copyright (C) 2004 Stefan Reinauer
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
18 /* TODO: Clean up MOLisms in a decent way */
21 #include "libopenbios/bindings.h"
22 #include "libc/string.h"
23 #include "libopenbios/ofmem.h"
30 #include "asm/processor.h"
32 #include "osi_calls.h"
35 #define BIT(n) (1U<<(31-(n)))
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
);
42 /****************************************************************
43 * Memory usage (before of_quiesce is called)
47 * 0x00000000 Exception vectors
48 * 0x00004000 Free space
49 * 0x01e00000 Open Firmware (us)
50 * 0x01f00000 OF allocations
52 * 0x02000000- Free space
54 * Allocations grow downwards from 0x01e00000
56 ****************************************************************/
58 #define HASH_SIZE (2 << 15)
59 #define SEGR_BASE 0x400 /* segment number range to use */
61 #define FREE_BASE_1 0x00004000
62 #define OF_CODE_START 0x01e00000
63 /* #define OF_MALLOC_BASE 0x01f00000 */
65 #define OF_MALLOC_BASE _end
67 #define HASH_BASE (0x02000000 - HASH_SIZE)
68 #define FREE_BASE_2 0x02000000
70 #define RAMSIZE 0x02000000 /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */
72 static ofmem_t s_ofmem
;
74 #define IO_BASE 0x80000000
75 #define OFMEM (&s_ofmem)
77 static inline unsigned long
83 static inline unsigned long
89 static ucell
get_heap_top( void )
94 static inline size_t ALIGN_SIZE(size_t x
, size_t a
)
96 return (x
+ a
- 1) & ~(a
-1);
99 ofmem_t
* ofmem_arch_get_private(void)
104 void* ofmem_arch_get_malloc_base(void)
106 return OF_MALLOC_BASE
;
109 ucell
ofmem_arch_get_heap_top(void)
111 return get_heap_top();
114 ucell
ofmem_arch_get_virt_top(void)
119 void ofmem_arch_unmap_pages(ucell virt
, ucell size
)
121 /* kill page mappings in provided range */
124 void ofmem_arch_early_map_pages(ucell phys
, ucell virt
, ucell size
, ucell mode
)
129 /************************************************************************/
130 /* OF private allocations */
131 /************************************************************************/
136 return ofmem_malloc(size
);
142 return ofmem_free(ptr
);
146 realloc( void *ptr
, size_t size
)
148 return ofmem_realloc(ptr
, size
);
152 /************************************************************************/
154 /************************************************************************/
156 ucell
ofmem_arch_default_translation_mode( ucell phys
)
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 */
165 /************************************************************************/
166 /* page fault handler */
167 /************************************************************************/
170 ea_to_phys( ucell ea
, ucell
*mode
)
174 /* hardcode our translation needs */
175 if( ea
>= OF_CODE_START
&& ea
< FREE_BASE_2
) {
176 *mode
= ofmem_arch_default_translation_mode( ea
);
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
);
187 *mode
= ofmem_arch_default_translation_mode( phys
);
189 #ifdef I_WANT_MOLISMS
190 forth_segv_handler( (char*)ea
);
193 /* print_virt_range(); */
194 /* print_phys_range(); */
201 hash_page( ucell ea
, ucell phys
, ucell mode
)
203 static int next_grab_slot
=0;
204 unsigned long *upte
, cmp
, hash1
;
208 vsid
= (ea
>>28) + SEGR_BASE
;
209 cmp
= BIT(0) | (vsid
<< 7) | ((ea
& 0x0fffffff) >> 22);
212 hash1
^= (ea
>> 12) & 0xffff;
213 hash1
&= (get_hash_size() - 1) >> 6;
215 pp
= (mPTE_t
*)(get_hash_base() + (hash1
<< 6));
216 upte
= (unsigned long*)pp
;
218 /* replace old translation */
219 for( found
=0, i
=0; !found
&& i
<8; i
++ )
220 if( cmp
== upte
[i
*2] )
223 /* otherwise use a free slot */
224 for( i
=0; !found
&& i
<8; i
++ )
228 /* out of slots, just evict one */
230 i
= next_grab_slot
+ 1;
231 next_grab_slot
= (next_grab_slot
+ 1) % 8;
235 upte
[i
*2+1] = (phys
& ~0xfff) | mode
;
237 asm volatile( "tlbie %0" :: "r"(ea
) );
241 dsi_exception( void )
243 unsigned long dar
, dsisr
;
247 asm volatile("mfdar %0" : "=r" (dar
) : );
248 asm volatile("mfdsisr %0" : "=r" (dsisr
) : );
250 //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
252 phys
= ea_to_phys(dar
, &mode
);
253 hash_page( dar
, phys
, mode
);
257 isi_exception( void )
259 unsigned long nip
, srr1
;
263 asm volatile("mfsrr0 %0" : "=r" (nip
) : );
264 asm volatile("mfsrr1 %0" : "=r" (srr1
) : );
266 //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
268 phys
= ea_to_phys(nip
, &mode
);
269 hash_page( nip
, phys
, mode
);
273 /************************************************************************/
275 /************************************************************************/
278 setup_mmu( unsigned long code_base
, unsigned long code_size
, unsigned long ramsize
)
280 unsigned long sdr1
= HASH_BASE
| ((HASH_SIZE
-1) >> 16);
281 unsigned long sr_base
= (0x20 << 24) | SEGR_BASE
;
285 asm volatile("mtsdr1 %0" :: "r" (sdr1
) );
286 for( i
=0; i
<16; i
++ ) {
288 asm volatile("mtsrin %0,%1" :: "r" (sr_base
+ i
), "r" (j
) );
290 asm volatile("mfmsr %0" : "=r" (msr
) : );
291 msr
|= MSR_IR
| MSR_DR
;
292 asm volatile("mtmsr %0" :: "r" (msr
) );
298 ofmem_t
*ofmem
= OFMEM
;
299 /* In case we can't rely on memory being zero initialized */
300 memset(ofmem
, 0, sizeof(ofmem
));
302 ofmem
->ramsize
= RAMSIZE
;
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 );