|
@@ -879,3 +879,149 @@ static void __init pci_reserve_io(void)
|
|
|
#ifdef CONFIG_DEBUG_LL
|
|
|
void __init debug_ll_io_init(void)
|
|
|
{
|
|
|
+ struct map_desc map;
|
|
|
+
|
|
|
+ debug_ll_addr(&map.pfn, &map.virtual);
|
|
|
+ if (!map.pfn || !map.virtual)
|
|
|
+ return;
|
|
|
+ map.pfn = __phys_to_pfn(map.pfn);
|
|
|
+ map.virtual &= PAGE_MASK;
|
|
|
+ map.length = PAGE_SIZE;
|
|
|
+ map.type = MT_DEVICE;
|
|
|
+ create_mapping(&map);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static void * __initdata vmalloc_min =
|
|
|
+ (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
|
|
|
+
|
|
|
+/*
|
|
|
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
|
|
|
+ * bytes. This can be used to increase (or decrease) the vmalloc
|
|
|
+ * area - the default is 240m.
|
|
|
+ */
|
|
|
+static int __init early_vmalloc(char *arg)
|
|
|
+{
|
|
|
+ unsigned long vmalloc_reserve = memparse(arg, NULL);
|
|
|
+
|
|
|
+ if (vmalloc_reserve < SZ_16M) {
|
|
|
+ vmalloc_reserve = SZ_16M;
|
|
|
+ printk(KERN_WARNING
|
|
|
+ "vmalloc area too small, limiting to %luMB\n",
|
|
|
+ vmalloc_reserve >> 20);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) {
|
|
|
+ vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M);
|
|
|
+ printk(KERN_WARNING
|
|
|
+ "vmalloc area is too big, limiting to %luMB\n",
|
|
|
+ vmalloc_reserve >> 20);
|
|
|
+ }
|
|
|
+
|
|
|
+ vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+early_param("vmalloc", early_vmalloc);
|
|
|
+
|
|
|
+phys_addr_t arm_lowmem_limit __initdata = 0;
|
|
|
+
|
|
|
+void __init sanity_check_meminfo(void)
|
|
|
+{
|
|
|
+ int i, j, highmem = 0;
|
|
|
+
|
|
|
+ for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
|
|
|
+ struct membank *bank = &meminfo.bank[j];
|
|
|
+ *bank = meminfo.bank[i];
|
|
|
+
|
|
|
+ if (bank->start > ULONG_MAX)
|
|
|
+ highmem = 1;
|
|
|
+
|
|
|
+#ifdef CONFIG_HIGHMEM
|
|
|
+ if (__va(bank->start) >= vmalloc_min ||
|
|
|
+ __va(bank->start) < (void *)PAGE_OFFSET)
|
|
|
+ highmem = 1;
|
|
|
+
|
|
|
+ bank->highmem = highmem;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Split those memory banks which are partially overlapping
|
|
|
+ * the vmalloc area greatly simplifying things later.
|
|
|
+ */
|
|
|
+ if (!highmem && __va(bank->start) < vmalloc_min &&
|
|
|
+ bank->size > vmalloc_min - __va(bank->start)) {
|
|
|
+ if (meminfo.nr_banks >= NR_BANKS) {
|
|
|
+ printk(KERN_CRIT "NR_BANKS too low, "
|
|
|
+ "ignoring high memory\n");
|
|
|
+ } else {
|
|
|
+ memmove(bank + 1, bank,
|
|
|
+ (meminfo.nr_banks - i) * sizeof(*bank));
|
|
|
+ meminfo.nr_banks++;
|
|
|
+ i++;
|
|
|
+ bank[1].size -= vmalloc_min - __va(bank->start);
|
|
|
+ bank[1].start = __pa(vmalloc_min - 1) + 1;
|
|
|
+ bank[1].highmem = highmem = 1;
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+ bank->size = vmalloc_min - __va(bank->start);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ bank->highmem = highmem;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Highmem banks not allowed with !CONFIG_HIGHMEM.
|
|
|
+ */
|
|
|
+ if (highmem) {
|
|
|
+ printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
|
|
|
+ "(!CONFIG_HIGHMEM).\n",
|
|
|
+ (unsigned long long)bank->start,
|
|
|
+ (unsigned long long)bank->start + bank->size - 1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check whether this memory bank would entirely overlap
|
|
|
+ * the vmalloc area.
|
|
|
+ */
|
|
|
+ if (__va(bank->start) >= vmalloc_min ||
|
|
|
+ __va(bank->start) < (void *)PAGE_OFFSET) {
|
|
|
+ printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
|
|
|
+ "(vmalloc region overlap).\n",
|
|
|
+ (unsigned long long)bank->start,
|
|
|
+ (unsigned long long)bank->start + bank->size - 1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check whether this memory bank would partially overlap
|
|
|
+ * the vmalloc area.
|
|
|
+ */
|
|
|
+ if (__va(bank->start + bank->size - 1) >= vmalloc_min ||
|
|
|
+ __va(bank->start + bank->size - 1) <= __va(bank->start)) {
|
|
|
+ unsigned long newsize = vmalloc_min - __va(bank->start);
|
|
|
+ printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
|
|
|
+ "to -%.8llx (vmalloc region overlap).\n",
|
|
|
+ (unsigned long long)bank->start,
|
|
|
+ (unsigned long long)bank->start + bank->size - 1,
|
|
|
+ (unsigned long long)bank->start + newsize - 1);
|
|
|
+ bank->size = newsize;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit)
|
|
|
+ arm_lowmem_limit = bank->start + bank->size;
|
|
|
+
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+#ifdef CONFIG_HIGHMEM
|
|
|
+ if (highmem) {
|
|
|
+ const char *reason = NULL;
|
|
|
+
|
|
|
+ if (cache_is_vipt_aliasing()) {
|
|
|
+ /*
|
|
|
+ * Interactions between kmap and other mappings
|
|
|
+ * make highmem support with aliasing VIPT caches
|
|
|
+ * rather difficult.
|
|
|
+ */
|
|
|
+ reason = "with VIPT aliasing cache";
|
|
|
+ }
|
|
|
+ if (reason) {
|
|
|
+ printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
|