|
|
1.1 ! root 1: /* ! 2: * <ofmem_sparc64.c> ! 3: * ! 4: * OF Memory manager ! 5: * ! 6: * Copyright (C) 1999-2004 Samuel Rydh ([email protected]) ! 7: * Copyright (C) 2004 Stefan Reinauer ! 8: * ! 9: * This program is free software; you can redistribute it and/or ! 10: * modify it under the terms of the GNU General Public License ! 11: * as published by the Free Software Foundation ! 12: * ! 13: */ ! 14: ! 15: #include "config.h" ! 16: #include "libopenbios/bindings.h" ! 17: #include "libc/string.h" ! 18: #include "ofmem_sparc64.h" ! 19: #include "spitfire.h" ! 20: ! 21: #define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8)) ! 22: ! 23: #define MEMSIZE ((256 + 512) * 1024) ! 24: static union { ! 25: char memory[MEMSIZE]; ! 26: ofmem_t ofmem; ! 27: } s_ofmem_data; ! 28: ! 29: #define OFMEM (&s_ofmem_data.ofmem) ! 30: #define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE) ! 31: ! 32: translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans; ! 33: ! 34: extern uint64_t qemu_mem_size; ! 35: ! 36: static inline size_t ALIGN_SIZE(size_t x, size_t a) ! 37: { ! 38: return (x + a - 1) & ~(a-1); ! 39: } ! 40: ! 41: static ucell get_heap_top( void ) ! 42: { ! 43: return (ucell)(TOP_OF_RAM - ALIGN_SIZE(sizeof(retain_t), 8)); ! 44: } ! 45: ! 46: ofmem_t* ofmem_arch_get_private(void) ! 47: { ! 48: return OFMEM; ! 49: } ! 50: ! 51: void* ofmem_arch_get_malloc_base(void) ! 52: { ! 53: return OF_MALLOC_BASE; ! 54: } ! 55: ! 56: ucell ofmem_arch_get_heap_top(void) ! 57: { ! 58: return get_heap_top(); ! 59: } ! 60: ! 61: ucell ofmem_arch_get_virt_top(void) ! 62: { ! 63: return (ucell)TOP_OF_RAM; ! 64: } ! 65: ! 66: phys_addr_t ofmem_arch_get_phys_top(void) ! 67: { ! 68: ofmem_t *ofmem = ofmem_arch_get_private(); ! 69: ! 70: return ofmem->ramsize; ! 71: } ! 72: ! 73: ucell ofmem_arch_get_iomem_base(void) ! 74: { ! 75: /* Currently unused */ ! 76: return 0; ! 77: } ! 78: ! 79: ucell ofmem_arch_get_iomem_top(void) ! 80: { ! 81: /* Currently unused */ ! 82: return 0; ! 83: } ! 84: ! 85: retain_t *ofmem_arch_get_retained(void) ! 86: { ! 87: /* Retained area is at the top of physical RAM */ ! 88: return (retain_t *)(qemu_mem_size - sizeof(retain_t)); ! 89: } ! 90: ! 91: int ofmem_arch_get_translation_entry_size(void) ! 92: { ! 93: /* Return size of a single MMU package translation property entry in cells */ ! 94: return 3; ! 95: } ! 96: ! 97: void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) ! 98: { ! 99: /* Generate translation property entry for SPARC. While there is no ! 100: formal documentation for this, both Linux kernel and OpenSolaris sources ! 101: expect a translation property entry to have the following layout: ! 102: ! 103: virtual address ! 104: length ! 105: mode ! 106: */ ! 107: ! 108: transentry[0] = t->virt; ! 109: transentry[1] = t->size; ! 110: transentry[2] = t->mode; ! 111: } ! 112: ! 113: /* Return the size of a memory available entry given the phandle in cells */ ! 114: int ofmem_arch_get_available_entry_size(phandle_t ph) ! 115: { ! 116: if (ph == s_phandle_memory) { ! 117: return 1 + ofmem_arch_get_physaddr_cellsize(); ! 118: } else { ! 119: return 1 + 1; ! 120: } ! 121: } ! 122: ! 123: /* Generate memory available property entry for Sparc64 */ ! 124: void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size) ! 125: { ! 126: int i = 0; ! 127: ! 128: if (ph == s_phandle_memory) { ! 129: i += ofmem_arch_encode_physaddr(availentry, start); ! 130: } else { ! 131: availentry[i++] = start; ! 132: } ! 133: ! 134: availentry[i] = size; ! 135: } ! 136: ! 137: /************************************************************************/ ! 138: /* misc */ ! 139: /************************************************************************/ ! 140: ! 141: int ofmem_arch_get_physaddr_cellsize(void) ! 142: { ! 143: return 1; ! 144: } ! 145: ! 146: int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) ! 147: { ! 148: p[0] = value; ! 149: return 1; ! 150: } ! 151: ! 152: ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) ! 153: { ! 154: /* Writable, cacheable */ ! 155: /* not privileged and not locked */ ! 156: return SPITFIRE_TTE_CP | SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE; ! 157: } ! 158: ! 159: ucell ofmem_arch_io_translation_mode( phys_addr_t phys ) ! 160: { ! 161: /* Writable, not privileged and not locked */ ! 162: return SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE; ! 163: } ! 164: ! 165: /************************************************************************/ ! 166: /* init / cleanup */ ! 167: /************************************************************************/ ! 168: ! 169: static int remap_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode ) ! 170: { ! 171: ofmem_claim_phys(phys, size, 0); ! 172: ofmem_claim_virt(virt, size, 0); ! 173: ofmem_map_page_range(phys, virt, size, mode); ! 174: if (!(mode & SPITFIRE_TTE_LOCKED)) { ! 175: OFMEM_TRACE("remap_page_range clearing translation " FMT_ucellx ! 176: " -> " FMT_ucellx " " FMT_ucellx " mode " FMT_ucellx "\n", ! 177: virt, phys, size, mode ); ! 178: ofmem_arch_unmap_pages(virt, size); ! 179: } ! 180: return 0; ! 181: } ! 182: ! 183: #define RETAIN_MAGIC 0x1100220033004400 ! 184: ! 185: void ofmem_init( void ) ! 186: { ! 187: retain_t *retained = ofmem_arch_get_retained(); ! 188: int i; ! 189: ! 190: memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); ! 191: s_ofmem_data.ofmem.ramsize = qemu_mem_size; ! 192: ! 193: /* inherit translations set up by entry.S */ ! 194: ofmem_walk_boot_map(remap_page_range); ! 195: ! 196: /* Map the memory */ ! 197: ofmem_map_page_range(0, 0, qemu_mem_size, 0x36); ! 198: ! 199: if (!(retained->magic == RETAIN_MAGIC)) { ! 200: OFMEM_TRACE("ofmem_init: no retained magic found, creating\n"); ! 201: retained->magic = RETAIN_MAGIC; ! 202: retained->numentries = 0; ! 203: } else { ! 204: OFMEM_TRACE("ofmem_init: retained magic found, total %lld mappings\n", retained->numentries); ! 205: ! 206: /* Mark physical addresses as used so they are not reallocated */ ! 207: for (i = 0; i < retained->numentries; i++) { ! 208: ofmem_claim_phys(retained->retain_phys_range[i].start, ! 209: retained->retain_phys_range[i].size, 0); ! 210: } ! 211: ! 212: /* Reset retained area for next reset */ ! 213: retained->magic = RETAIN_MAGIC; ! 214: retained->numentries = 0; ! 215: } ! 216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.