|
|
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: ! 124: void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size, ucell mode) ! 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.