#include <xen/domain_page.h>
#include <xen/sched.h>
#include <asm/byteorder.h>
+#include <asm/setup.h>
#include "kernel.h"
#define DTB_MAGIC 0xd00dfeed
-static void copy_from_flash(void *dst, paddr_t flash, unsigned long len)
+/**
+ * copy_from_paddr - copy data from a physical address
+ * @dst: destination virtual address
+ * @paddr: source physical address
+ * @len: length to copy
+ */
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
{
void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
- printk("Copying %#lx bytes from flash %"PRIpaddr" to %p",
- len, flash, dst);
-
while (len) {
paddr_t p;
unsigned long l, s;
- p = flash >> PAGE_SHIFT;
- s = flash & (PAGE_SIZE-1);
+ p = paddr >> PAGE_SHIFT;
+ s = paddr & (PAGE_SIZE-1);
l = min(PAGE_SIZE - s, len);
set_fixmap(FIXMAP_MISC, p, DEV_SHARED);
memcpy(dst, src + s, l);
- flash += l;
+ paddr += l;
dst += l;
len -= l;
}
/*
* Check for an appended DTB.
*/
- copy_from_flash(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, sizeof(dtb_hdr));
+ copy_from_paddr(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, sizeof(dtb_hdr));
if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) {
end += be32_to_cpu(dtb_hdr.total_size);
}
if ( info->kernel_img == NULL )
panic("Cannot allocate temporary buffer for kernel.\n");
- copy_from_flash(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE);
+ copy_from_paddr(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE);
if ( (rc = elf_init(&info->elf.elf, info->kernel_img, KERNEL_FLASH_SIZE )) != 0 )
return rc;
unsigned long xenheap_mfn_start, xenheap_mfn_end;
unsigned long xenheap_virt_end;
+unsigned long frametable_base_mfn;
unsigned long frametable_virt_end;
/* Map a 4k page in a fixmap entry */
unsigned long frametable_size = nr_pages * sizeof(struct page_info);
unsigned long base_mfn;
+ frametable_base_mfn = ps >> PAGE_SHIFT;
+
/* Round up to 32M boundary */
frametable_size = (frametable_size + 0x1ffffff) & ~0x1ffffff;
base_mfn = alloc_boot_pages(frametable_size >> PAGE_SHIFT, 5);
/* TODO: setup_idle_pagetable(); */
}
+static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
+{
+ paddr_t ram_start;
+ paddr_t ram_end;
+ paddr_t ram_size;
+ unsigned long ram_pages;
+ unsigned long heap_pages, xenheap_pages, domheap_pages;
+ unsigned long dtb_pages;
+ unsigned long boot_mfn_start, boot_mfn_end;
+
+ /*
+ * TODO: only using the first RAM bank for now. The heaps and the
+ * frame table assume RAM is physically contiguous.
+ */
+ ram_start = early_info.mem.bank[0].start;
+ ram_size = early_info.mem.bank[0].size;
+ ram_end = ram_start + ram_size;
+ ram_pages = ram_size >> PAGE_SHIFT;
+
+ /*
+ * Calculate the sizes for the heaps using these constraints:
+ *
+ * - heaps must be 32 MiB aligned
+ * - must not include Xen itself
+ * - xen heap must be at most 1 GiB
+ *
+ * XXX: needs a platform with at least 1GiB of RAM or the dom
+ * heap will be empty and no domains can be created.
+ */
+ heap_pages = (ram_size >> PAGE_SHIFT) - (32 << (20 - PAGE_SHIFT));
+ xenheap_pages = min(1ul << (30 - PAGE_SHIFT), heap_pages);
+ domheap_pages = heap_pages - xenheap_pages;
+
+ printk("Xen heap: %lu pages Dom heap: %lu pages\n", xenheap_pages, domheap_pages);
+
+ setup_xenheap_mappings(ram_start >> PAGE_SHIFT, xenheap_pages);
+
+ /*
+ * Need a single mapped page for populating bootmem_region_list
+ * and enough mapped pages for copying the DTB.
+ *
+ * TODO: The DTB (and other payloads) are assumed to be towards
+ * the start of RAM.
+ */
+ dtb_pages = (dtb_size + PAGE_SIZE-1) >> PAGE_SHIFT;
+ boot_mfn_start = xenheap_mfn_end - dtb_pages - 1;
+ boot_mfn_end = xenheap_mfn_end;
+
+ init_boot_pages(pfn_to_paddr(boot_mfn_start), pfn_to_paddr(boot_mfn_end));
+
+ /*
+ * Copy the DTB.
+ *
+ * TODO: handle other payloads too.
+ */
+ device_tree_flattened = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
+ copy_from_paddr(device_tree_flattened, dtb_paddr, dtb_size);
+
+ /* Add non-xenheap memory */
+ init_boot_pages(pfn_to_paddr(xenheap_mfn_start + xenheap_pages),
+ pfn_to_paddr(xenheap_mfn_start + xenheap_pages + domheap_pages));
+
+ setup_frametable_mappings(ram_start, ram_end);
+
+ /* Add xenheap memory that was not already added to the boot
+ allocator. */
+ init_xenheap_pages(pfn_to_paddr(xenheap_mfn_start),
+ pfn_to_paddr(boot_mfn_start));
+
+ end_boot_allocator();
+}
+
void __init start_xen(unsigned long boot_phys_offset,
unsigned long arm_type,
unsigned long atag_paddr)
{
void *fdt;
+ size_t fdt_size;
int i;
fdt = (void *)BOOT_MISC_VIRT_START
+ (atag_paddr & ((1 << SECOND_SHIFT) - 1));
- device_tree_early_init(fdt);
+ fdt_size = device_tree_early_init(fdt);
setup_pagetables(boot_phys_offset);
init_xen_time();
- /* TODO: This needs some thought, as well as device-tree mapping.
- * For testing, assume that the whole xenheap is contiguous in RAM */
- setup_xenheap_mappings(0x8000000, 0x40000); /* 1 GB @ 512GB */
- /* Must pass a single mapped page for populating bootmem_region_list. */
- init_boot_pages(pfn_to_paddr(xenheap_mfn_start),
- pfn_to_paddr(xenheap_mfn_start+1));
-
- /* Add non-xenheap memory */
- init_boot_pages(0x8040000000, 0x80c0000000); /* 2 GB @513GB */
-
- /* TODO Make sure Xen's own pages aren't added
- * -- the memory above doesn't include our relocation target. */
- /* TODO Handle payloads too */
-
- /* TODO Need to find actual memory, for now use 4GB at 512GB */
- setup_frametable_mappings(0x8000000000ULL, 0x8100000000UL);
-
- /* Add xenheap memory */
- init_xenheap_pages(pfn_to_paddr(xenheap_mfn_start+1),
- pfn_to_paddr(xenheap_mfn_end));
-
- end_boot_allocator();
+ setup_mm(atag_paddr, fdt_size);
/* Setup Hyp vector base */
WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR);
#include <libfdt.h>
struct dt_early_info __initdata early_info;
+void *device_tree_flattened;
static void __init get_val(const u32 **cell, u32 cells, u64 *val)
{
/**
* device_tree_early_init - initialize early info from a DTB
* @fdt: flattened device tree binary
+ *
+ * Returns the size of the DTB.
*/
-void __init device_tree_early_init(const void *fdt)
+size_t __init device_tree_early_init(const void *fdt)
{
int ret;
early_scan(fdt);
early_print_info();
+
+ return fdt_totalsize(fdt);
}
/**
struct page_info *page, int readonly);
#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
+/* MFN of the first page in the frame table. */
+extern unsigned long frametable_base_mfn;
extern unsigned long max_page;
extern unsigned long total_pages;
})
#define max_pdx max_page
-/* XXX Assume everything in the 40-bit physical alias 0x8000000000 for now */
-#define pfn_to_pdx(pfn) ((pfn) - 0x8000000UL)
-#define pdx_to_pfn(pdx) ((pdx) + 0x8000000UL)
+#define pfn_to_pdx(pfn) (pfn)
+#define pdx_to_pfn(pdx) (pdx)
#define virt_to_pdx(va) virt_to_mfn(va)
#define pdx_to_virt(pdx) mfn_to_virt(pdx)
/* Convert between machine frame numbers and page-info structures. */
-#define mfn_to_page(mfn) (frame_table + pfn_to_pdx(mfn))
-#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table))
+#define mfn_to_page(mfn) (frame_table + (pfn_to_pdx(mfn) - frametable_base_mfn))
+#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_mfn)
#define __page_to_mfn(pg) page_to_mfn(pg)
#define __mfn_to_page(mfn) mfn_to_page(mfn)
#include <public/version.h>
+void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
+
void arch_get_xen_caps(xen_capabilities_info_t *info);
int construct_dom0(struct domain *d);
};
extern struct dt_early_info early_info;
+extern void *device_tree_flattened;
-void device_tree_early_init(const void *fdt);
+size_t device_tree_early_init(const void *fdt);
paddr_t device_tree_get_xen_paddr(void);
#endif