|
|
1.1 root 1: /*
2: * <ofmem_sparc32.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"
1.1.1.2 ! root 18: #include "arch/sparc32/ofmem_sparc32.h"
1.1 root 19: #include "asm/asi.h"
20: #include "pgtsrmmu.h"
21:
22: #define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
23:
1.1.1.2 ! root 24: #define MEMSIZE (256 * 1024)
1.1 root 25: static union {
26: char memory[MEMSIZE];
27: ofmem_t ofmem;
28: } s_ofmem_data;
29:
30: #define OFMEM (&s_ofmem_data.ofmem)
31: #define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
32:
33: translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
34:
35: extern uint32_t qemu_mem_size;
36:
37: static inline size_t ALIGN_SIZE(size_t x, size_t a)
38: {
39: return (x + a - 1) & ~(a-1);
40: }
41:
42: static ucell get_heap_top( void )
43: {
44: return (ucell)TOP_OF_RAM;
45: }
46:
47: ofmem_t* ofmem_arch_get_private(void)
48: {
49: return OFMEM;
50: }
51:
52: void* ofmem_arch_get_malloc_base(void)
53: {
54: return OF_MALLOC_BASE;
55: }
56:
57: ucell ofmem_arch_get_heap_top(void)
58: {
59: return get_heap_top();
60: }
61:
62: ucell ofmem_arch_get_virt_top(void)
63: {
64: return (ucell)TOP_OF_RAM;
65: }
66:
67: phys_addr_t ofmem_arch_get_phys_top(void)
68: {
69: ofmem_t *ofmem = ofmem_arch_get_private();
70:
71: return (uintptr_t)ofmem->ramsize - 0x1000000;
72: }
73:
74: ucell ofmem_arch_get_iomem_base(void)
75: {
76: return pointer2cell(&_end);
77: }
78:
79: ucell ofmem_arch_get_iomem_top(void)
80: {
81: return pointer2cell(&_iomem);
82: }
83:
84: retain_t *ofmem_arch_get_retained(void)
85: {
86: /* Not used */
87: return 0;
88: }
89:
90: int ofmem_arch_get_physaddr_cellsize(void)
91: {
92: return 2;
93: }
94:
95: int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
96: {
97: int n = 0;
98:
99: p[n++] = value >> 32;
100: p[n++] = value;
101:
102: return n;
103: }
104:
105: int ofmem_arch_get_translation_entry_size(void)
106: {
107: /* Return size of a single MMU package translation property entry in cells */
108: return 3;
109: }
110:
111: void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
112: {
113: /* Generate translation property entry for SPARC. While there is no
114: formal documentation for this, both Linux kernel and OpenSolaris sources
115: expect a translation property entry to have the following layout:
116:
117: virtual address
118: length
119: mode
120: */
121:
122: transentry[0] = t->virt;
123: transentry[1] = t->size;
124: transentry[2] = t->mode;
125: }
126:
127: /* Return the size of a memory available entry given the phandle in cells */
128: int ofmem_arch_get_available_entry_size(phandle_t ph)
129: {
130: return 1 + ofmem_arch_get_physaddr_cellsize();
131: }
132:
133: /* Generate memory available property entry for Sparc32 */
134: void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
135: {
1.1.1.2 ! root 136: int i = 0;
1.1 root 137:
138: i += ofmem_arch_encode_physaddr(availentry, start);
139: availentry[i] = size;
140: }
141:
1.1.1.2 ! root 142: /* Unmap a set of pages */
! 143: void ofmem_arch_unmap_pages(ucell virt, ucell size)
! 144: {
! 145: /* Currently do nothing */
! 146: }
! 147:
! 148: /* Map a set of pages */
! 149: void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
! 150: {
! 151: unsigned long npages, off;
! 152: uint32_t pte;
! 153: unsigned long pa;
! 154:
! 155: off = phys & (PAGE_SIZE - 1);
! 156: npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE;
! 157: phys &= ~(uint64_t)(PAGE_SIZE - 1);
! 158:
! 159: while (npages-- != 0) {
! 160: pa = find_pte(virt, 1);
! 161:
! 162: pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4);
! 163: pte |= mode;
! 164:
! 165: *(uint32_t *)pa = pte;
! 166:
! 167: virt += PAGE_SIZE;
! 168: phys += PAGE_SIZE;
! 169: }
! 170: }
! 171:
! 172: /* Architecture-specific OFMEM helpers */
! 173: unsigned long
! 174: find_pte(unsigned long va, int alloc)
! 175: {
! 176: uint32_t pte;
! 177: void *p;
! 178: unsigned long pa;
! 179: int ret;
! 180:
! 181: pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)];
! 182: if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
! 183: if (alloc) {
! 184: ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int),
! 185: SRMMU_PTRS_PER_PMD * sizeof(int));
! 186: if (ret != 0)
! 187: return ret;
! 188: pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4);
! 189: l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte;
! 190: /* barrier() */
! 191: } else {
! 192: return -1;
! 193: }
! 194: }
! 195:
! 196: pa = (pte & 0xFFFFFFF0) << 4;
! 197: pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2;
! 198: pte = *(uint32_t *)pa2va(pa);
! 199: if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
! 200: if (alloc) {
! 201: ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *),
! 202: SRMMU_PTRS_PER_PTE * sizeof(void *));
! 203: if (ret != 0)
! 204: return ret;
! 205: pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4);
! 206: *(uint32_t *)pa2va(pa) = pte;
! 207: } else {
! 208: return -2;
! 209: }
! 210: }
! 211:
! 212: pa = (pte & 0xFFFFFFF0) << 4;
! 213: pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2;
! 214:
! 215: return pa2va(pa);
! 216: }
! 217:
1.1 root 218: /************************************************************************/
219: /* misc */
220: /************************************************************************/
221:
222: ucell ofmem_arch_default_translation_mode( phys_addr_t phys )
223: {
224: return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV;
225: }
226:
227: ucell ofmem_arch_io_translation_mode( phys_addr_t phys )
228: {
229: return SRMMU_REF | SRMMU_PRIV;
230: }
231:
232: /************************************************************************/
233: /* init / cleanup */
234: /************************************************************************/
235:
236: void ofmem_init( void )
237: {
238: memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
239: s_ofmem_data.ofmem.ramsize = qemu_mem_size;
240:
241: /* Claim reserved physical addresses at top of RAM */
242: ofmem_claim_phys(ofmem_arch_get_phys_top(), s_ofmem_data.ofmem.ramsize - ofmem_arch_get_phys_top(), 0);
243:
244: /* Claim OpenBIOS reserved space */
245: ofmem_claim_virt(0xffd00000, 0x300000, 0);
246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.