source: trunk/packages/xen-3.1/xen-3.1/xen/arch/powerpc/memory.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 6.4 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 *
16 * Copyright IBM Corp. 2006, 2007
17 *
18 * Authors: Dan Poff <poff@us.ibm.com>
19 *          Jimi Xenidis <jimix@watson.ibm.com>
20 */
21#include <xen/sched.h>
22#include <xen/mm.h>
23#include <xen/numa.h>
24#include "of-devtree.h"
25#include "oftree.h"
26#include "rtas.h"
27
28#define DEBUG
29#ifdef DEBUG
30#define DBG(fmt...) printk(fmt)
31#else
32#define DBG(fmt...)
33#endif
34
35/*
36 * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
37 * page_info table and allocation bitmap.
38 */
39static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
40integer_param("xenheap_megabytes", opt_xenheap_megabytes);
41
42unsigned long xenheap_phys_end;
43static uint nr_pages;
44static ulong xenheap_size;
45
46struct membuf {
47    ulong start;
48    ulong size;
49};
50
51typedef void (*walk_mem_fn)(struct membuf *, uint);
52
53static void set_max_page(struct membuf *mb, uint entries)
54{
55    int i;
56
57    for (i = 0; i < entries; i++) {
58        ulong end_page;
59
60        printk("  %016lx: %016lx\n", mb[i].start, mb[i].size);
61        nr_pages += mb[i].size >> PAGE_SHIFT;
62
63        end_page = (mb[i].start + mb[i].size) >> PAGE_SHIFT;
64        if (end_page > max_page)
65            max_page = end_page;
66    }
67}
68
69/* mark all memory from modules onward as unused */
70static void heap_init(struct membuf *mb, uint entries)
71{
72    int i;
73    ulong start_blk;
74    ulong end_blk = 0;
75
76    for (i = 0; i < entries; i++) {
77        start_blk = mb[i].start;
78        end_blk = start_blk + mb[i].size;
79
80        if (start_blk < xenheap_phys_end) {
81            if (xenheap_phys_end > end_blk) {
82                panic("xenheap spans LMB\n");
83            }
84            if (xenheap_phys_end == end_blk)
85                continue;
86
87            start_blk = xenheap_phys_end;
88        }
89
90        DBG("boot free: %016lx - %016lx\n", start_blk, end_blk);
91        init_boot_pages(start_blk, end_blk);
92        total_pages += (end_blk - start_blk) >> PAGE_SHIFT;
93    }
94}
95
96static void ofd_walk_mem(void *m, walk_mem_fn fn)
97{
98    ofdn_t n;
99    uint p_len;
100    struct membuf mb[8];
101    static char name[] = "memory";
102
103    n = ofd_node_find_by_prop(m, OFD_ROOT, "device_type", name, sizeof(name));
104    while (n > 0) {
105
106        p_len = ofd_getprop(m, n, "reg", mb, sizeof (mb));
107        if (p_len <= 0) {
108            panic("ofd_getprop(): failed\n");
109        }
110        if (p_len > sizeof(mb))
111            panic("%s: buffer is not big enuff for this firmware: "
112                  "0x%lx < 0x%x\n", __func__, sizeof(mb), p_len);
113
114        fn(mb, p_len / sizeof(mb[0]));
115        n = ofd_node_find_next(m, n);
116    }
117}
118
119void memory_init(module_t *mod, int mcount)
120{
121    ulong eomem;
122    ulong bitmap_start = ~0UL;
123    ulong bitmap_end = 0;
124    ulong bitmap_size;
125    ulong xh_pages;
126    ulong start;
127    ulong end;
128    int pos;
129
130    /* lets find out how much memory there is and set max_page */
131    max_page = 0;
132    printk("Physical RAM map:\n");
133    ofd_walk_mem((void *)oftree, set_max_page);
134    eomem = max_page << PAGE_SHIFT;
135    if (eomem == 0) {
136        panic("ofd_walk_mem() failed\n");
137    }
138
139    xh_pages = opt_xenheap_megabytes << (20 - PAGE_SHIFT);
140
141    /* While we are allocating HTABS from The Xen Heap we need it to
142     * be larger */
143    xh_pages += nr_pages >> 5;
144
145    xenheap_phys_end = xh_pages << PAGE_SHIFT;
146    printk("End of Xen Area: %luMiB (%luKiB)\n",
147           xenheap_phys_end >> 20, xenheap_phys_end >> 10);
148
149    printk("End of RAM: %luMiB (%luKiB)\n", eomem >> 20, eomem >> 10);
150
151    /* The boot allocator requires one bit per page. Find a spot for it. */
152    bitmap_size = max_page / 8;
153    pos = boot_of_mem_avail(0, &start, &end);
154    while (pos >= 0) {
155        if (end - start >= bitmap_size) {
156            bitmap_start = start;
157            bitmap_end = init_boot_allocator(bitmap_start);
158            printk("boot allocator @ %lx - %lx\n", bitmap_start, bitmap_end);
159            break;
160        }
161        pos = boot_of_mem_avail(pos, &start, &end);
162    }
163    if (bitmap_start == ~0UL)
164        panic("Couldn't find 0x%lx bytes for boot allocator.", bitmap_size);
165
166    /* allow everything else to be allocated */
167    total_pages = 0;
168    ofd_walk_mem((void *)oftree, heap_init);
169    if (total_pages == 0)
170        panic("heap_init: failed");
171
172    if (total_pages > max_page)
173        panic("total_pages > max_page: 0x%lx > 0x%lx\n",
174              total_pages, max_page);
175
176    DBG("total_pages: 0x%016lx\n", total_pages);
177
178    init_frametable();
179    init_machine_to_phys_table();
180
181    numa_initmem_init(0, max_page);
182
183    /* Domain heap gets all the unclaimed memory. */
184    end_boot_allocator();
185
186    /* Create initial xen heap by finding non-reserved memory. */
187    pos = boot_of_mem_avail(0, &start, &end);
188    while (pos >= 0) {
189        if (end == ~0UL)
190            end = xenheap_phys_end;
191
192        /* Problem: the bitmap itself is not reserved. */
193        if ((start >= bitmap_start) && (start < bitmap_end)) {
194            /* Start is inside bitmap. */
195            start = bitmap_end;
196        }
197        if ((end > bitmap_start) && (end <= bitmap_end)) {
198            /* End is inside bitmap. */
199            end = bitmap_start;
200        }
201        if ((start < bitmap_start) && (end > bitmap_end)) {
202            /* Range encompasses bitmap. First free low part, then high. */
203            xenheap_size += bitmap_start - start;
204            DBG("xenheap: %016lx - %016lx\n", start, bitmap_start);
205            init_xenheap_pages(start, bitmap_start);
206            start = bitmap_end;
207        }
208
209        xenheap_size += end - start;
210        DBG("xenheap: %016lx - %016lx\n", start, end);
211        init_xenheap_pages(start, end);
212
213        pos = boot_of_mem_avail(pos, &start, &end);
214    }
215
216    printk("Xen Heap: %luMiB (%luKiB)\n",
217           xenheap_size >> 20, xenheap_size >> 10);
218
219    eomem = avail_domheap_pages();
220    printk("Dom Heap: %luMiB (%luKiB)\n",
221           (eomem << PAGE_SHIFT) >> 20,
222           (eomem << PAGE_SHIFT) >> 10);
223}
Note: See TracBrowser for help on using the repository browser.