Patchwork [23/40] xenner: kernel: generic MM functionality

login
register
mail settings
Submitter Alexander Graf
Date Nov. 1, 2010, 3:01 p.m.
Message ID <1288623713-28062-24-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/69804/
State New
Headers show

Comments

Alexander Graf - Nov. 1, 2010, 3:01 p.m.
Xenner does its own memory management bookkeeping which can be kept
platform agnostic. This patch adds that.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 pc-bios/xenner/xenner-mm.c |  105 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/xenner/xenner-mm.c

Patch

diff --git a/pc-bios/xenner/xenner-mm.c b/pc-bios/xenner/xenner-mm.c
new file mode 100644
index 0000000..ccbd48a
--- /dev/null
+++ b/pc-bios/xenner/xenner-mm.c
@@ -0,0 +1,105 @@ 
+/*
+ *  Copyright (C) Red Hat 2007
+ *  Copyright (C) Novell Inc. 2010
+ *
+ *  Author(s): Gerd Hoffmann <kraxel@redhat.com>
+ *             Alexander Graf <agraf@suse.de>
+ *
+ *  Xenner generic memory management
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; under version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+static int heap_type = HEAP_EMU;
+static void *heap_emu = NULL;
+static void *heap_high_start = NULL;
+static void *heap_high = NULL;
+
+unsigned long heap_size(void)
+{
+    unsigned long r = 0;
+
+    switch (heap_type) {
+        case HEAP_EMU:
+            r = (unsigned long)heap_emu - (unsigned long)_vstop;
+            break;
+        case HEAP_HIGH:
+            r = (unsigned long)heap_high - (unsigned long)heap_high_start;
+            break;
+    }
+
+    return r;
+}
+
+void switch_heap(int _heap_type)
+{
+    if ((_heap_type == HEAP_HIGH) && !heap_high) {
+#if defined(CONFIG_32BIT)
+        heap_high = (void*)(uintptr_t)XEN_IPT;
+#elif defined(CONFIG_64BIT)
+        uintptr_t mfn_guest = emudev_get(EMUDEV_CONF_GUEST_START_PFN, 0);
+        uintptr_t init_pt_pfn = emudev_get(EMUDEV_CONF_PFN_INIT_PT, 0);
+
+        heap_high = map_page(frame_to_addr(mfn_guest + init_pt_pfn));
+#endif
+        heap_high_start = heap_high;
+    }
+
+    switch (_heap_type) {
+    case HEAP_EMU:
+    case HEAP_HIGH:
+        heap_type = _heap_type;
+        break;
+    }
+}
+
+void *get_pages(int pages, const char *purpose)
+{
+    void **heap_cur = &heap_emu;
+    void *ptr;
+
+    if (!heap_emu) {
+        heap_emu = _vstop;
+    }
+
+    switch (heap_type) {
+        case HEAP_EMU:
+            heap_cur = &heap_emu;
+            break;
+        case HEAP_HIGH:
+            heap_cur = &heap_high;
+            break;
+    }
+
+    ptr = *heap_cur;
+    *heap_cur += pages * PAGE_SIZE;
+    printk(2, "%s: %d page(s) at %p (for %s)\n",
+           __FUNCTION__, pages, ptr, purpose);
+    memset(ptr, 0, pages * PAGE_SIZE);
+    return ptr;
+}
+
+void *get_memory(int bytes, const char *purpose)
+{
+    int pages = (bytes + PAGE_SIZE -1) / PAGE_SIZE;
+    return get_pages(pages, purpose);
+}
+
+void paging_start(struct xen_cpu *cpu)
+{
+    ureg_t cr3_mfn;
+
+    cr3_mfn = cpu->init_ctxt->ctrlreg[3] >> PAGE_SHIFT;
+    update_emu_mappings(cr3_mfn);
+    pv_write_cr3(cpu, cr3_mfn);
+}