[PATCH 10/10] tilo: allocate kernel memory dynamically on sun4u

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allocate memory for kernel image dynamically on sun4u. This allows to
boot bigger modern day kernels.

External root image is not yet supported, but this can be workarounded
by embedding the rootfs into the kernel with CONFIG_INITRAMFS_SOURCE.

Signed-off-by: Aaro Koskinen <aaro.koskinen@xxxxxx>
---
 tilo/tilo.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 106 insertions(+), 11 deletions(-)

diff --git a/tilo/tilo.c b/tilo/tilo.c
index d2fcd97b525f..75772b77ca49 100644
--- a/tilo/tilo.c
+++ b/tilo/tilo.c
@@ -171,6 +171,69 @@ extern struct ImageInfo image_table[4];	/* Sun4 kernel, Sun4c/d/m kernel, Sun4u
 
 #define HDRS_TAG	(('H'<<24) | ('d'<<16) | ('r'<<8) | 'S')
 
+static char *sun4u_memory_find (unsigned int len)
+{
+	int n, node, i;
+	struct p1275_mem {
+		unsigned long long phys;
+		unsigned long long size;
+	} *p = (struct p1275_mem *)0;
+	unsigned int virt = 0x40000000;
+	unsigned long long phys = 0, phys_base;
+
+	p = (struct p1275_mem *)malloc(2048);
+
+	node = prom_finddevice("/memory");
+
+	n = prom_getproplen(node, "available");
+
+	if (!n || n == -1 ||
+	    prom_getproperty(node, "available", (char *)p, 2048) == -1) {
+		free (p);
+		printf("Could not get available property\n");
+		return (char *)0;
+	}
+
+	phys = 0;
+	n /= sizeof(*p);
+
+	phys_base = ~(unsigned long long)0;
+	for (i = 0; i < n; i++) {
+		if (p[i].phys < phys_base)
+			phys_base = p[i].phys;
+	}
+
+	for (i = 0; i < n; i++) {
+		/* Do not mess with first 16 Megs of memory */
+		if (p[i].phys == phys_base) {
+			if (p[i].size <= 0x1000000)
+				continue;
+			p[i].phys += 0x1000000;
+			p[i].size -= 0x1000000;
+		}
+
+		if (p[i].size >= len) {
+			phys = p[i].phys;
+			break;
+		}
+	}
+
+	free (p);
+
+	if (!phys) {
+		printf("Could not find any available memory\n");
+		return (char *)0;
+	}
+
+	if (prom_map(PROM_MAP_DEFAULT, (unsigned long long)len, virt, phys) ==
+	    -1) {
+		printf("Could not map memory\n");
+		return (char *)0;
+	}
+
+	return (char *)virt + 0x4000;
+}
+
 void parse_executable(char *base, int image_len)
 {
 	union {
@@ -275,7 +338,7 @@ void parse_executable(char *base, int image_len)
 
 char *my_main (struct linux_romvec *promvec, void *cifh, void *cifs)
 {
-char *orig_code,*moved_code,*moved_ramdisk,*moved_kernel,*kernel_base;
+char *orig_code,*moved_code,*moved_ramdisk = NULL,*moved_kernel,*kernel_base;
 unsigned *p,*q = NULL;
 int kernel_number;
 char *kernel_end, *kernel_limit;
@@ -307,21 +370,53 @@ char *kernel_end, *kernel_limit;
 	}
 	    				
     orig_code = (char*) 0x4000;
-    moved_code = (char*) MOVED_BASE;
-    moved_ramdisk = (char*)((long)(moved_code - image_table[ROOT_IMAGE].packed_len) & ~0xfff);
-    moved_kernel = (char*)((long)(moved_ramdisk - image_table[kernel_number].packed_len) & ~0xfff);
+
+    /*
+     * On sun4u we can allocate more memory and relocate the kernel.
+     */
+    if (kernel_number == SUN4U_KERNEL) {
+        unsigned int size;
+
+	for (size = 64 * 1024 * 1024; size >= 4 * 1024 * 1024;
+	     size -= 4 * 1024 * 1024) {
+		kernel_base = sun4u_memory_find(size);
+		if (kernel_base)
+			break;
+	}
+	if (!kernel_base)
+		goto no_mem;
+	kernel_limit = kernel_base + size;
+	gzminp = (unsigned char *)orig_code +
+		 image_table[kernel_number].packed_start;
+	if (image_table[ROOT_IMAGE].packed_len ||
+	    image_table[kernel_number].root_start) {
+		printf("External root image not yet supported - disabling.\n");
+		image_table[kernel_number].root_start = 0;
+		image_table[ROOT_IMAGE].packed_len = 0;
+	}
+    } else {
+no_mem:
+	moved_code = (char*)MOVED_BASE;
+	moved_ramdisk = (char*)((long)(moved_code -
+				image_table[ROOT_IMAGE].packed_len) & ~0xfff);
+	moved_kernel = (char*)((long)(moved_ramdisk -
+			       image_table[kernel_number].packed_len) & ~0xfff);
 #ifdef TILO_DEBUG
-    printf("Locations: moved_code=%x  moved_ramdisk=%x moved_kernel=%x\n",
-	   moved_code, moved_ramdisk, moved_kernel);
+	printf("Locations: moved_code=%x  moved_ramdisk=%x moved_kernel=%x\n",
+	       moved_code, moved_ramdisk, moved_kernel);
 #endif
-    memmove (moved_ramdisk, orig_code + image_table[ROOT_IMAGE].packed_start, image_table[ROOT_IMAGE].packed_len);
-    memmove (moved_kernel, orig_code + image_table[kernel_number].packed_start, image_table[kernel_number].packed_len);
+	memmove(moved_ramdisk, orig_code + image_table[ROOT_IMAGE].packed_start,
+		image_table[ROOT_IMAGE].packed_len);
+	memmove(moved_kernel,
+		orig_code + image_table[kernel_number].packed_start,
+		image_table[kernel_number].packed_len);
+
+	kernel_base = (char*) 0x4000;
+	kernel_limit = moved_kernel;
+    }
 
-    gzminp = (unsigned char *)moved_kernel;		/* decompress kernel */
-    kernel_base = (char*) 0x4000;
     kernel_end = kernel_base +
 		 ((image_table[kernel_number].unpacked_len + 0xfff) & ~0xfff);
-    kernel_limit = moved_kernel;
 
     if (kernel_end > kernel_limit) {
 	printf("No space to decompress the kernel.\n");
-- 
1.8.4.4

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Development]     [DCCP]     [Linux ARM Development]     [Linux]     [Photo]     [Yosemite Help]     [Linux ARM Kernel]     [Linux SCSI]     [Linux x86_64]     [Linux Hams]

  Powered by Linux