Procházet zdrojové kódy

efHeterogeneousSynchronization currentMemoryDefinition.c 李欣儒 commit at 2021-03-04

李欣儒 před 4 roky
rodič
revize
059bbf2a49

+ 169 - 0
efHeterogeneousSynchronization/dataSharedMemory/currentMemoryDefinition.c

@@ -242,3 +242,172 @@ extern char _end;
 #define K_KERNEL_IMAGE_END	(START_ADDR + KERNEL_SIZE)
 
 /* Define to where we may have to decompress the kernel image, before
+   we move it to the final position, in case of overlap. This will be
+   above the final position of the kernel.
+
+   Regardless of overlap, we move the INITRD image to the end of this
+   copy area, because there needs to be a buffer area after the kernel
+   for "bootmem" anyway.
+*/
+#define K_COPY_IMAGE_START	NEXT_PAGE(K_KERNEL_IMAGE_END)
+/* Reserve one page below INITRD for the new stack. */
+#define K_INITRD_START \
+    NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
+#define K_COPY_IMAGE_END \
+    (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
+#define K_COPY_IMAGE_SIZE \
+    NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
+
+void
+start_kernel(void)
+{
+	int must_move = 0;
+
+	/* Initialize these for the decompression-in-place situation,
+	   which is the smallest amount of work and most likely to
+	   occur when using the normal START_ADDR of the kernel
+	   (currently set to 16MB, to clear all console code.
+	*/
+	unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
+	unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
+
+	unsigned long initrd_image_start = K_INITRD_START;
+
+	/*
+	 * Note that this crufty stuff with static and envval
+	 * and envbuf is because:
+	 *
+	 * 1. Frequently, the stack is short, and we don't want to overrun;
+	 * 2. Frequently the stack is where we are going to copy the kernel to;
+	 * 3. A certain SRM console required the GET_ENV output to stack.
+	 *    ??? A comment in the aboot sources indicates that the GET_ENV
+	 *    destination must be quadword aligned.  Might this explain the
+	 *    behaviour, rather than requiring output to the stack, which
+	 *    seems rather far-fetched.
+	 */
+	static long nbytes;
+	static char envval[256] __attribute__((aligned(8)));
+	register unsigned long asm_sp asm("30");
+
+	SP_on_entry = asm_sp;
+
+	srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
+
+	/* Validity check the HWRPB. */
+	if (INIT_HWRPB->pagesize != 8192) {
+		srm_printk("Expected 8kB pages, got %ldkB\n",
+		           INIT_HWRPB->pagesize >> 10);
+		return;
+	}
+	if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
+		srm_printk("Expected vptb at %p, got %p\n",
+			   VPTB, (void *)INIT_HWRPB->vptb);
+		return;
+	}
+
+	/* PALcode (re)initialization. */
+	pal_init();
+
+	/* Get the parameter list from the console environment variable. */
+	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
+	if (nbytes < 0 || nbytes >= sizeof(envval)) {
+		nbytes = 0;
+	}
+	envval[nbytes] = '\0';
+
+#ifdef DEBUG_ADDRESSES
+	srm_printk("START_ADDR 0x%lx\n", START_ADDR);
+	srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
+	srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
+	srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
+#endif
+
+	/* Since all the SRM consoles load the BOOTP image at virtual
+	 * 0x20000000, we have to ensure that the physical memory
+	 * pages occupied by that image do NOT overlap the physical
+	 * address range where the kernel wants to be run.  This
+	 * causes real problems when attempting to cdecompress the
+	 * former into the latter... :-(
+	 *
+	 * So, we may have to decompress/move the kernel/INITRD image
+	 * virtual-to-physical someplace else first before moving
+	 * kernel /INITRD to their final resting places... ;-}
+	 *
+	 * Sigh...
+	 */
+
+	/* First, check to see if the range of addresses occupied by
+	   the bootstrapper part of the BOOTP image include any of the
+	   physical pages into which the kernel will be placed for
+	   execution.
+
+	   We only need check on the final kernel image range, since we
+	   will put the INITRD someplace that we can be sure is not
+	   in conflict.
+	 */
+	if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
+			K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
+	{
+		srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
+		__halt();
+	}
+
+	/* Next, check to see if the range of addresses occupied by
+	   the compressed kernel/INITRD/stack portion of the BOOTP
+	   image include any of the physical pages into which the
+	   decompressed kernel or the INITRD will be placed for
+	   execution.
+	 */
+	if (check_range(V_DATA_START, V_DATA_END,
+			K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
+	{
+#ifdef DEBUG_ADDRESSES
+		srm_printk("OVERLAP: cannot decompress in place\n");
+#endif
+		uncompressed_image_start = K_COPY_IMAGE_START;
+		uncompressed_image_end = K_COPY_IMAGE_END;
+		must_move = 1;
+
+		/* Finally, check to see if the range of addresses
+		   occupied by the compressed kernel/INITRD part of
+		   the BOOTP image include any of the physical pages
+		   into which that part is to be copied for
+		   decompression.
+		*/
+		while (check_range(V_DATA_START, V_DATA_END,
+				   uncompressed_image_start,
+				   uncompressed_image_end))
+		{
+#if 0
+			uncompressed_image_start += K_COPY_IMAGE_SIZE;
+			uncompressed_image_end += K_COPY_IMAGE_SIZE;
+			initrd_image_start += K_COPY_IMAGE_SIZE;
+#else
+			/* Keep as close as possible to end of BOOTP image. */
+			uncompressed_image_start += PAGE_SIZE;
+			uncompressed_image_end += PAGE_SIZE;
+			initrd_image_start += PAGE_SIZE;
+#endif
+		}
+	}
+
+	srm_printk("Starting to load the kernel with args '%s'\n", envval);
+
+#ifdef DEBUG_ADDRESSES
+	srm_printk("Decompressing the kernel...\n"
+		   "...from 0x%lx to 0x%lx size 0x%x\n",
+		   V_DATA_START,
+		   uncompressed_image_start,
+		   KERNEL_SIZE);
+#endif
+        decompress_kernel((void *)uncompressed_image_start,
+			  (void *)V_DATA_START,
+			  KERNEL_SIZE, KERNEL_Z_SIZE);
+
+	/*
+	 * Now, move things to their final positions, if/as required.
+	 */
+
+#ifdef INITRD_IMAGE_SIZE
+
+	/* First, we always move the INITRD image, if present. */