|
|
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.