/* * Done by Dietmar Hahn * * Description: Special ia64 memory management. * Parts are taken from FreeBSD. * **************************************************************************** * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #define MAX_MEM_AREA 5 paddr_t phys_avail[MAX_MEM_AREA * 2]; int phys_avail_cnt; uint64_t physmem; /* * These variables are defined in the linker script minios_ia64.lds * to get the size of the kernel. */ extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[]; uint64_t kernstart, kernend, kernsize, kernpstart, kernpend; #ifdef HAVE_LIBC uint8_t _heap[512 * 1024]; unsigned long heap = (unsigned long)_heap, brk = (unsigned long)_heap, heap_mapped = (unsigned long)_heap + sizeof(_heap), heap_end = (unsigned long)_heap + sizeof(_heap); #endif /* Print the available memory chunks. */ static void print_phys_avail(void) { int i; printk("Physical memory chunk(s):\n"); for (i = 0; phys_avail[i + 1] != 0; i += 2) { int size = phys_avail[i + 1] - phys_avail[i]; printk("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[i], phys_avail[i + 1] - 1, size, size / PAGE_SIZE); } } void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) { uint64_t ms, me; int i, j; uint64_t m, n; kernstart = trunc_page(_text); kernend = roundup_page(_end); kernpstart = trunc_page(ia64_tpa(kernstart)); kernpend = roundup_page(kernpstart + (kernend - kernstart)); kernsize = kernpend - kernpstart; ms = roundup_page(machineFwG.mach_mem_start); me = trunc_page(machineFwG.mach_mem_start+machineFwG.mach_mem_size); memset((void*)phys_avail, 0, sizeof(phys_avail)); /* 1. Check where the kernel lies in physical memory. */ physmem = me - ms; if ((ms <= kernpend) && (kernpstart <= me)) { if (ms < kernpstart) { /* There is a part before the kernel. */ PRINT_BV(" Found chunk before kernel: 0x%lx - 0x%lx\n", ms, kernpstart); phys_avail[phys_avail_cnt] = ms; phys_avail[phys_avail_cnt+1] = kernpstart; phys_avail_cnt += 2; } if (kernpend < me) { /* There is a part behind the kernel. */ PRINT_BV(" Found chunk behind kernel: 0x%lx - 0x%lx\n", kernpend, me); phys_avail[phys_avail_cnt] = kernpend; phys_avail[phys_avail_cnt+1] = me; phys_avail_cnt += 2; } } else { /* One big chunk */ PRINT_BV(" Found big chunk: 0x%lx - 0x%lx\n", ms, me); phys_avail[phys_avail_cnt] = ms; phys_avail[phys_avail_cnt + 1] = me; phys_avail_cnt += 2; } phys_avail[phys_avail_cnt] = 0; print_phys_avail(); /* * In this first version I only look for the biggest mem area. */ for (i = j = m = n = 0; i < phys_avail_cnt; i += 2) { n = page_to_pfn(phys_avail[i + 1]) - page_to_pfn(phys_avail[i]); if (n > m) { m = n; j = i; } } *start_pfn_p = page_to_pfn(phys_avail[j]); *max_pfn_p = page_to_pfn(phys_avail[j +1 ]); } /* Currently only a dummy function. */ void arch_init_demand_mapping_area(unsigned long max_pfn) { max_pfn = max_pfn; } unsigned long allocate_ondemand(unsigned long n, unsigned long alignment) { return 0; } /* Helper function used in gnttab.c. */ void do_map_frames(unsigned long addr, const unsigned long *f, unsigned long n, unsigned long stride, unsigned long increment, domid_t id, int *err, unsigned long prot) { /* TODO */ ASSERT(0); } void* map_frames_ex(const unsigned long* frames, unsigned long n, unsigned long stride, unsigned long increment, unsigned long alignment, domid_t id, int *err, unsigned long prot) { /* TODO: incomplete! */ ASSERT(n == 1 || (stride == 0 && increment == 1)); ASSERT(id == DOMID_SELF); ASSERT(prot == 0); return (void*) __va(frames[0] << PAGE_SHIFT); } int unmap_frames(unsigned long virt_addr, unsigned long num_frames) { /* TODO */ ASSERT(0); } unsigned long alloc_contig_pages(int order, unsigned int addr_bits) { /* TODO */ ASSERT(0); } void arch_init_p2m(unsigned long max_pfn) { printk("Warn: p2m map not implemented.\n"); }