6 * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
7 * Copyright (C) 2004 Stefan Reinauer
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
16 #include "libopenbios/bindings.h"
17 #include "libc/string.h"
18 #include "arch/sparc32/ofmem_sparc32.h"
22 #define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
24 #define MEMSIZE (256 * 1024)
30 #define OFMEM (&s_ofmem_data.ofmem)
31 #define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
33 #define OFMEM_PHYS_RESERVED 0x1000000
35 translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
37 extern uint32_t qemu_mem_size;
39 static inline size_t ALIGN_SIZE(size_t x, size_t a)
41 return (x + a - 1) & ~(a-1);
44 static ucell get_heap_top( void )
46 return (ucell)TOP_OF_RAM;
49 ofmem_t* ofmem_arch_get_private(void)
54 void* ofmem_arch_get_malloc_base(void)
56 return OF_MALLOC_BASE;
59 ucell ofmem_arch_get_heap_top(void)
61 return get_heap_top();
64 ucell ofmem_arch_get_virt_top(void)
66 return (ucell)OFMEM_VIRT_TOP;
69 ucell ofmem_arch_get_iomem_base(void)
71 return pointer2cell(&_end);
74 ucell ofmem_arch_get_iomem_top(void)
76 return pointer2cell(&_iomem);
79 retain_t *ofmem_arch_get_retained(void)
85 int ofmem_arch_get_physaddr_cellsize(void)
90 int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
100 int ofmem_arch_get_translation_entry_size(void)
102 /* Return size of a single MMU package translation property entry in cells */
106 void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
108 /* Generate translation property entry for SPARC. While there is no
109 formal documentation for this, both Linux kernel and OpenSolaris sources
110 expect a translation property entry to have the following layout:
117 transentry[0] = t->virt;
118 transentry[1] = t->size;
119 transentry[2] = t->mode;
122 /* Return the size of a memory available entry given the phandle in cells */
123 int ofmem_arch_get_available_entry_size(phandle_t ph)
125 return 1 + ofmem_arch_get_physaddr_cellsize();
128 /* Generate memory available property entry for Sparc32 */
129 void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
133 i += ofmem_arch_encode_physaddr(availentry, start);
134 availentry[i] = size;
137 /* Unmap a set of pages */
138 void ofmem_arch_unmap_pages(ucell virt, ucell size)
143 for (i = 0; i < size; i += PAGE_SIZE) {
144 pa = find_pte(virt, 0);
149 srmmu_flush_whole_tlb();
152 /* Map a set of pages */
153 void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
155 unsigned long npages, off;
159 off = phys & (PAGE_SIZE - 1);
160 npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE;
161 phys &= ~(uint64_t)(PAGE_SIZE - 1);
163 while (npages-- != 0) {
164 pa = find_pte(virt, 1);
166 pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4);
169 *(uint32_t *)pa = pte;
176 /* Architecture-specific OFMEM helpers */
178 find_pte(unsigned long va, int alloc)
185 pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)];
186 if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
188 ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int),
189 SRMMU_PTRS_PER_PMD * sizeof(int));
192 pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4);
193 l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte;
200 pa = (pte & 0xFFFFFFF0) << 4;
201 pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2;
202 pte = *(uint32_t *)pa2va(pa);
203 if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
205 ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *),
206 SRMMU_PTRS_PER_PTE * sizeof(void *));
209 pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4);
210 *(uint32_t *)pa2va(pa) = pte;
216 pa = (pte & 0xFFFFFFF0) << 4;
217 pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2;
222 /************************************************************************/
224 /************************************************************************/
226 ucell ofmem_arch_default_translation_mode( phys_addr_t phys )
228 return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV;
231 ucell ofmem_arch_io_translation_mode( phys_addr_t phys )
233 return SRMMU_REF | SRMMU_PRIV;
236 /************************************************************************/
238 /************************************************************************/
240 void ofmem_init( void )
242 memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
243 s_ofmem_data.ofmem.ramsize = qemu_mem_size;
245 /* Mark the first page as non-free */
246 ofmem_claim_virt(0, PAGE_SIZE, 0);
248 /* Claim reserved physical addresses at top of RAM */
249 ofmem_claim_phys(s_ofmem_data.ofmem.ramsize - OFMEM_PHYS_RESERVED, OFMEM_PHYS_RESERVED, 0);
251 /* Claim OpenBIOS reserved space */
252 ofmem_claim_virt(0xffd00000, 0x200000, 0);