1 | /* |
---|
2 | * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> |
---|
3 | * |
---|
4 | * Description: Special ia64 memory management. |
---|
5 | * Parts are taken from FreeBSD. |
---|
6 | * |
---|
7 | **************************************************************************** |
---|
8 | * |
---|
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
10 | * of this software and associated documentation files (the "Software"), to |
---|
11 | * deal in the Software without restriction, including without limitation the |
---|
12 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
---|
13 | * sell copies of the Software, and to permit persons to whom the Software is |
---|
14 | * furnished to do so, subject to the following conditions: |
---|
15 | * |
---|
16 | * The above copyright notice and this permission notice shall be included in |
---|
17 | * all copies or substantial portions of the Software. |
---|
18 | * |
---|
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
25 | * DEALINGS IN THE SOFTWARE. |
---|
26 | */ |
---|
27 | |
---|
28 | |
---|
29 | #include "os.h" |
---|
30 | #include "mm.h" |
---|
31 | |
---|
32 | |
---|
33 | #define MAX_MEM_AREA 5 |
---|
34 | paddr_t phys_avail[MAX_MEM_AREA * 2]; |
---|
35 | int phys_avail_cnt; |
---|
36 | uint64_t physmem; |
---|
37 | |
---|
38 | /* |
---|
39 | * These variables are defined in the linker script minios_ia64.lds |
---|
40 | * to get the size of the kernel. |
---|
41 | */ |
---|
42 | extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[]; |
---|
43 | |
---|
44 | uint64_t kernstart, kernend, kernsize, kernpstart, kernpend; |
---|
45 | |
---|
46 | /* Print the available memory chunks. */ |
---|
47 | static void |
---|
48 | print_phys_avail(void) |
---|
49 | { |
---|
50 | int i; |
---|
51 | |
---|
52 | printk("Physical memory chunk(s):\n"); |
---|
53 | for (i = 0; phys_avail[i + 1] != 0; i += 2) { |
---|
54 | int size = phys_avail[i + 1] - phys_avail[i]; |
---|
55 | printk("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", |
---|
56 | phys_avail[i], phys_avail[i + 1] - 1, |
---|
57 | size, size / PAGE_SIZE); |
---|
58 | } |
---|
59 | } |
---|
60 | |
---|
61 | void |
---|
62 | arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) |
---|
63 | { |
---|
64 | uint64_t ms, me; |
---|
65 | int i, j; |
---|
66 | uint64_t m, n; |
---|
67 | |
---|
68 | kernstart = trunc_page(_text); |
---|
69 | kernend = roundup_page(_end); |
---|
70 | |
---|
71 | kernpstart = trunc_page(ia64_tpa(kernstart)); |
---|
72 | kernpend = roundup_page(kernpstart + (kernend - kernstart)); |
---|
73 | kernsize = kernpend - kernpstart; |
---|
74 | |
---|
75 | ms = roundup_page(machineFwG.mach_mem_start); |
---|
76 | me = trunc_page(machineFwG.mach_mem_start+machineFwG.mach_mem_size); |
---|
77 | memset((void*)phys_avail, 0, sizeof(phys_avail)); |
---|
78 | /* 1. Check where the kernel lies in physical memory. */ |
---|
79 | physmem = me - ms; |
---|
80 | if ((ms <= kernpend) && (kernpstart <= me)) { |
---|
81 | if (ms < kernpstart) { /* There is a part before the kernel. */ |
---|
82 | PRINT_BV(" Found chunk before kernel: 0x%lx - 0x%lx\n", |
---|
83 | ms, kernpstart); |
---|
84 | phys_avail[phys_avail_cnt] = ms; |
---|
85 | phys_avail[phys_avail_cnt+1] = kernpstart; |
---|
86 | phys_avail_cnt += 2; |
---|
87 | } |
---|
88 | if (kernpend < me) { /* There is a part behind the kernel. */ |
---|
89 | PRINT_BV(" Found chunk behind kernel: 0x%lx - 0x%lx\n", |
---|
90 | kernpend, me); |
---|
91 | phys_avail[phys_avail_cnt] = kernpend; |
---|
92 | phys_avail[phys_avail_cnt+1] = me; |
---|
93 | phys_avail_cnt += 2; |
---|
94 | } |
---|
95 | } else { /* One big chunk */ |
---|
96 | PRINT_BV(" Found big chunk: 0x%lx - 0x%lx\n", ms, me); |
---|
97 | phys_avail[phys_avail_cnt] = ms; |
---|
98 | phys_avail[phys_avail_cnt + 1] = me; |
---|
99 | phys_avail_cnt += 2; |
---|
100 | } |
---|
101 | phys_avail[phys_avail_cnt] = 0; |
---|
102 | |
---|
103 | print_phys_avail(); |
---|
104 | /* |
---|
105 | * In this first version I only look for the biggest mem area. |
---|
106 | */ |
---|
107 | for (i = j = m = n = 0; i < phys_avail_cnt; i += 2) { |
---|
108 | n = page_to_pfn(phys_avail[i + 1]) - page_to_pfn(phys_avail[i]); |
---|
109 | if (n > m) { |
---|
110 | m = n; |
---|
111 | j = i; |
---|
112 | } |
---|
113 | } |
---|
114 | *start_pfn_p = page_to_pfn(phys_avail[j]); |
---|
115 | *max_pfn_p = page_to_pfn(phys_avail[j +1 ]); |
---|
116 | } |
---|
117 | |
---|
118 | /* Currently only a dummy function. */ |
---|
119 | void |
---|
120 | arch_init_demand_mapping_area(unsigned long max_pfn) |
---|
121 | { |
---|
122 | max_pfn = max_pfn; |
---|
123 | } |
---|
124 | |
---|
125 | /* Helper function used in gnttab.c. */ |
---|
126 | void* |
---|
127 | map_frames(unsigned long* frames, unsigned long n) |
---|
128 | { |
---|
129 | n = n; |
---|
130 | return (void*) __va(SWAP(frames[0]) << PAGE_SHIFT); |
---|
131 | } |
---|
132 | |
---|
133 | void arch_init_p2m(unsigned long max_pfn) |
---|
134 | { |
---|
135 | printk("Warn: p2m map not implemented.\n"); |
---|
136 | } |
---|