2 * tag: simple function library
4 * Copyright (C) 2003 Stefan Reinauer
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
10 #include "libc/vsprintf.h"
11 #include "libopenbios/bindings.h"
12 #include "arch/sparc32/ofmem_sparc32.h"
16 #include "libopenbios/sys_info.h"
20 #define NCTX_SWIFT 0x100
21 #define LOWMEMSZ 32 * 1024 * 1024
23 #ifdef CONFIG_DEBUG_MEM
24 #define DPRINTF(fmt, args...) \
25 do { printk(fmt , ##args); } while (0)
27 #define DPRINTF(fmt, args...)
30 /* Format a string and print it on the screen, just like the libc
33 int printk( const char *fmt, ... )
40 i = vsnprintf(buf, sizeof(buf), fmt, args);
49 * Allocatable memory chunk.
56 struct mem cdvmem; /* Current device virtual memory space */
58 unsigned int va_shift;
60 static unsigned long *context_table;
62 struct linux_mlist_v0 *ptphys;
63 struct linux_mlist_v0 *ptmap;
64 struct linux_mlist_v0 *ptavail;
66 /* Private functions for mapping between physical/virtual addresses */
68 va2pa(unsigned long va)
70 if ((va >= (unsigned long)&_start) &&
71 (va < (unsigned long)&_end))
80 if ((pa + va_shift >= (unsigned long)&_start) &&
81 (pa + va_shift < (unsigned long)&_end))
90 return ofmem_malloc(size);
94 realloc( void *ptr, size_t size )
96 return ofmem_realloc(ptr, size);
106 * Allocate memory. This is reusable.
109 mem_init(struct mem *t, char *begin, char *limit)
117 mem_alloc(struct mem *t, int size, int align)
122 // The alignment restrictions refer to physical, not virtual
124 pa = va2pa((unsigned long)t->curp) + (align - 1);
126 p = (char *)pa2va(pa);
128 if ((unsigned long)p >= (unsigned long)t->uplim ||
129 (unsigned long)p + size > (unsigned long)t->uplim)
137 * D5.3 pgmap@ ( va -- pte )
143 unsigned long va, pa;
147 pa = find_pte(va, 0);
148 if (pa == 1 || pa == 2)
150 pte = *(uint32_t *)pa;
151 DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
160 * D5.3 pgmap! ( pte va -- )
166 unsigned long va, pa;
171 pa = find_pte(va, 1);
172 *(uint32_t *)pa = pte;
173 DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
177 * D5.3 map-pages ( pa space va size -- )
190 pa |= POP() & 0xffffffff;
192 ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
195 char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
198 uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
200 ofmem_arch_map_pages(mpa, (unsigned long)va, size, ofmem_arch_default_translation_mode(mpa));
204 void obp_dumb_munmap(__attribute__((unused)) char *va,
205 __attribute__((unused)) unsigned int size)
207 DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size);
210 char *obp_memalloc(char *va, unsigned int size, unsigned int align)
215 DPRINTF("obp_memalloc: virta 0x%x, sz %d, align %d\n", (unsigned int)va, size, align);
217 /* Claim physical memory */
218 phys = ofmem_claim_phys(-1, size, align);
220 /* Claim virtual memory */
221 virt = ofmem_claim_virt(pointer2cell(va), size, 0);
224 ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
226 return cell2pointer(virt);
229 char *obp_dumb_memalloc(char *va, unsigned int size)
231 unsigned long align = size;
235 DPRINTF("obp_dumb_memalloc: virta 0x%x, sz %d\n", (unsigned int)va, size);
237 /* Solaris seems to assume that the returned value is physically aligned to size.
238 e.g. it is used for setting up page tables. */
240 /* Claim physical memory */
241 phys = ofmem_claim_phys(-1, size, align);
243 /* Claim virtual memory - if va == NULL then we choose va address */
245 virt = ofmem_claim_virt((ucell)-1, size, align);
247 virt = ofmem_claim_virt(pointer2cell(va), size, 0);
251 ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
253 return cell2pointer(virt);
256 void obp_dumb_memfree(char *va, unsigned size)
261 DPRINTF("obp_dumb_memfree: virta 0x%x, sz %d\n", (unsigned int)va, size);
263 phys = ofmem_translate(pointer2cell(va), &cellmode);
265 ofmem_unmap(pointer2cell(va), size);
266 ofmem_release_virt(pointer2cell(va), size);
267 ofmem_release_phys(phys, size);
270 /* Data fault handling routines */
272 extern unsigned int ignore_dfault;
275 static void srmmu_get_sfsr(void)
277 PUSH(srmmu_get_fstatus());
281 static void ignore_dfault_addr(void)
283 PUSH(pointer2cell(&ignore_dfault));
291 phys_addr_t virtregsize;
292 ofmem_t *ofmem = ofmem_arch_get_private();
294 /* Find the phandles for the /memory and /virtual-memory nodes */
296 fword("find-package");
298 s_phandle_memory = POP();
300 push_str("/virtual-memory");
301 fword("find-package");
303 s_phandle_mmu = POP();
305 ofmem_register(s_phandle_memory, s_phandle_mmu);
307 /* Setup /memory:reg (totphys) property */
308 memreg = malloc(3 * sizeof(ucell));
309 ofmem_arch_encode_physaddr(memreg, 0); /* physical base */
310 memreg[2] = (ucell)ofmem->ramsize; /* size */
313 fword("find-device");
314 PUSH(pointer2cell(memreg));
315 PUSH(3 * sizeof(ucell));
317 PUSH_ph(s_phandle_memory);
318 fword("encode-property");
320 /* Setup /virtual-memory:reg property */
321 virtregsize = ((phys_addr_t)((ucell)-1) + 1) / 2;
323 virtreg = malloc(6 * sizeof(ucell));
324 ofmem_arch_encode_physaddr(virtreg, 0);
325 virtreg[2] = virtregsize;
326 ofmem_arch_encode_physaddr(&virtreg[3], virtregsize);
327 virtreg[5] = virtregsize;
329 push_str("/virtual-memory");
330 fword("find-device");
331 PUSH(pointer2cell(virtreg));
332 PUSH(6 * sizeof(ucell));
334 PUSH_ph(s_phandle_mmu);
335 fword("encode-property");
338 fword("active-package!");
339 bind_func("pgmap@", pgmap_fetch);
340 bind_func("pgmap!", pgmap_store);
341 bind_func("map-pages", ob_map_pages);
343 /* Install data fault handler words for cpeek etc. */
344 PUSH_xt(bind_noname_func(srmmu_get_sfsr));
346 PUSH_xt(bind_noname_func(ignore_dfault_addr));
347 feval("to ignore-dfault");
351 * Switch page tables.
356 unsigned int addr, i;
357 unsigned long pa, va;
360 ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int),
361 NCTX_SWIFT * sizeof(int));
362 ofmem_posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int));
364 context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) |
367 for (i = 1; i < NCTX_SWIFT; i++) {
368 context_table[i] = SRMMU_ET_INVALID;
370 for (i = 0; i < 256; i++) {
371 l1[i] = SRMMU_ET_INVALID;
374 // text, rodata, data, and bss mapped to end of RAM
375 va = (unsigned long)&_start;
376 size = (unsigned long)&_end - (unsigned long)&_start;
378 ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
379 ofmem_map_page_range(pa, va, size, ofmem_arch_default_translation_mode(pa));
381 // 1:1 mapping for RAM (don't map page 0 to allow catching of NULL dereferences)
382 ofmem_arch_map_pages(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0));
383 ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0));
388 for (addr = 0; addr < 0x2000; addr += 0x10) {
389 __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
390 "r" (addr), "i" (ASI_M_DATAC_TAG));
391 __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
392 "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
394 srmmu_set_context(0);
395 srmmu_set_ctable_ptr(va2pa((unsigned long)context_table));
396 srmmu_flush_whole_tlb();