Module Name:    src
Committed By:   thorpej
Date:           Sat Jan  6 17:32:41 UTC 2024

Modified Files:
        src/sys/arch/virt68k/include: bootinfo.h vmparam.h
        src/sys/arch/virt68k/virt68k: bootinfo.c machdep.c

Log Message:
The RAM disk specified by bootinfo is not necessarily loaded along with
the static kernel image.  Map is separately and account for it in the
available memory segments.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/virt68k/include/bootinfo.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/virt68k/include/vmparam.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/virt68k/virt68k/bootinfo.c \
    src/sys/arch/virt68k/virt68k/machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/virt68k/include/bootinfo.h
diff -u src/sys/arch/virt68k/include/bootinfo.h:1.3 src/sys/arch/virt68k/include/bootinfo.h:1.4
--- src/sys/arch/virt68k/include/bootinfo.h:1.3	Tue Jan  2 17:13:03 2024
+++ src/sys/arch/virt68k/include/bootinfo.h	Sat Jan  6 17:32:40 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo.h,v 1.3 2024/01/02 17:13:03 thorpej Exp $	*/
+/*	$NetBSD: bootinfo.h,v 1.4 2024/01/06 17:32:40 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -142,6 +142,7 @@ extern size_t	bootinfo_mem_segments_igno
 extern struct bi_mem_info bootinfo_mem_segments[];
 extern struct bi_mem_info bootinfo_mem_segments_avail[];
 extern int	bootinfo_mem_nsegments;
+extern int	bootinfo_mem_nsegments_avail;
 extern vaddr_t	bootinfo_end;
 
 #define	bootinfo_dataptr(bi)	((void *)&(bi)->bi_data[0])

Index: src/sys/arch/virt68k/include/vmparam.h
diff -u src/sys/arch/virt68k/include/vmparam.h:1.1 src/sys/arch/virt68k/include/vmparam.h:1.2
--- src/sys/arch/virt68k/include/vmparam.h:1.1	Tue Jan  2 07:41:01 2024
+++ src/sys/arch/virt68k/include/vmparam.h	Sat Jan  6 17:32:40 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.1 2024/01/02 07:41:01 thorpej Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.2 2024/01/06 17:32:40 thorpej Exp $	*/
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -115,10 +115,15 @@
 
 /*
  * Constants which control the way the VM system deals with memory segments.
- * The Qemu virt68k platform only has a single memory segment.
+ *
+ * We generally assume there's just a single real memory segment on this
+ * platform, but we need to be able to deal with a "hole" left by a RAM
+ * disk if the loader provided one.  We optimize for the loader either
+ * plopping the RAM disk immediately after the kernel image or at the end
+ * of RAM, which would still leave us with a single large segment.
  */
-#define	VM_PHYSSEG_MAX		1
-#define	VM_PHYSSEG_STRAT	VM_PSTRAT_BSEARCH
+#define	VM_PHYSSEG_MAX		4
+#define	VM_PHYSSEG_STRAT	VM_PSTRAT_BIGFIRST
 
 #define	VM_NFREELIST		1
 #define	VM_FREELIST_DEFAULT	0

Index: src/sys/arch/virt68k/virt68k/bootinfo.c
diff -u src/sys/arch/virt68k/virt68k/bootinfo.c:1.3 src/sys/arch/virt68k/virt68k/bootinfo.c:1.4
--- src/sys/arch/virt68k/virt68k/bootinfo.c:1.3	Tue Jan  2 17:13:03 2024
+++ src/sys/arch/virt68k/virt68k/bootinfo.c	Sat Jan  6 17:32:41 2024
@@ -1,4 +1,4 @@
-/*      $NetBSD: bootinfo.c,v 1.3 2024/01/02 17:13:03 thorpej Exp $        */      
+/*      $NetBSD: bootinfo.c,v 1.4 2024/01/06 17:32:41 thorpej Exp $        */      
 
 /*-
  * Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bootinfo.c,v 1.3 2024/01/02 17:13:03 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bootinfo.c,v 1.4 2024/01/06 17:32:41 thorpej Exp $");
 
 #include "opt_md.h"
 
@@ -38,6 +38,8 @@ __KERNEL_RCSID(0, "$NetBSD: bootinfo.c,v
 #include <sys/cpu.h>
 #include <sys/rnd.h>
 
+#include <uvm/uvm_extern.h>
+
 #ifdef MEMORY_DISK_DYNAMIC
 #include <dev/md.h>
 #endif
@@ -58,10 +60,14 @@ size_t			bootinfo_mem_segments_ignored_b
 struct bi_mem_info	bootinfo_mem_segments[VM_PHYSSEG_MAX];
 struct bi_mem_info	bootinfo_mem_segments_avail[VM_PHYSSEG_MAX];
 int			bootinfo_mem_nsegments;
+int			bootinfo_mem_nsegments_avail;
 
 static paddr_t		bootinfo_console_addr;
 static bool		bootinfo_console_addr_valid;
 
+static uint32_t		bootinfo_initrd_start;
+static uint32_t		bootinfo_initrd_size;
+
 static bool
 bootinfo_set_console(paddr_t pa)
 {
@@ -141,9 +147,79 @@ bootinfo_add_mem(struct bi_record *bi)
 	m->mem_size = m68k_trunc_page(m->mem_size);
 	physmem += m->mem_size >> PGSHIFT;
 
-	bootinfo_mem_segments[bootinfo_mem_nsegments] = *m;
-	bootinfo_mem_segments_avail[bootinfo_mem_nsegments] = *m;
-	bootinfo_mem_nsegments++;
+	bootinfo_mem_segments[bootinfo_mem_nsegments++] = *m;
+	bootinfo_mem_segments_avail[bootinfo_mem_nsegments_avail++] = *m;
+}
+
+static inline void
+bootinfo_add_initrd(struct bi_record *bi)
+{
+	struct bi_mem_info *rd = bootinfo_dataptr(bi);
+
+	if (bootinfo_initrd_size == 0) {
+		bootinfo_initrd_start = rd->mem_addr;
+		bootinfo_initrd_size  = rd->mem_size;
+	}
+}
+
+static inline void
+bootinfo_reserve_initrd(void)
+{
+	if (bootinfo_initrd_size == 0) {
+		return;
+	}
+
+	paddr_t initrd_start = bootinfo_initrd_start;
+	paddr_t initrd_end   = bootinfo_initrd_start + bootinfo_initrd_size;
+	int i;
+
+	/* Page-align the RAM disk start/end. */
+	initrd_end = m68k_round_page(initrd_end);
+	initrd_start = m68k_trunc_page(initrd_start);
+
+	/*
+	 * XXX All if this code assumes that the RAM disk fits within
+	 * XXX a single memory segment.
+	 */
+
+	for (i = 0; i < bootinfo_mem_nsegments_avail; i++) {
+		/* Memory segment start/end already page-aligned. */
+		paddr_t seg_start = bootinfo_mem_segments_avail[i].mem_addr;
+		paddr_t seg_end = seg_start +
+		    bootinfo_mem_segments_avail[i].mem_size;
+
+		if (initrd_start >= seg_end ||
+		    initrd_end <= seg_start) {
+			/* Does not fall within this segment. */
+			continue;
+		}
+
+		if (initrd_start > seg_start && initrd_end < seg_end) {
+			/* We need to split this segment. */
+			/* XXX */
+			printf("WARNING: ignoring RAM disk that splits "
+			       "memory segment.\n");
+			bootinfo_initrd_size = 0;
+			return;
+		}
+
+		printf("Reserving RAM disk pages %p - %p from memory "
+		       "segment %d.\n", (void *)initrd_start,
+		       (void *)(initrd_end - 1), i);
+
+		if (initrd_start == seg_start) {
+			seg_start = initrd_end;
+		}
+
+		if (initrd_end == seg_end) {
+			seg_end = initrd_start;
+		}
+
+		/* Now adjust the segment. */
+		bootinfo_mem_segments_avail[i].mem_addr = seg_start;
+		bootinfo_mem_segments_avail[i].mem_size = seg_end - seg_start;
+		return;
+	}
 }
 
 static inline void
@@ -198,6 +274,10 @@ bootinfo_start(struct bi_record *first)
 			bootinfo_add_mem(bi);
 			break;
 
+		case BI_RAMDISK:
+			bootinfo_add_initrd(bi);
+			break;
+
 		case BI_VIRT_GF_TTY_BASE:
 			bootinfo_gf_tty_consinit(bi);
 			break;
@@ -209,6 +289,12 @@ bootinfo_start(struct bi_record *first)
 
 	/* Set bootinfo_end to be just past the BI_LAST record. */
 	bootinfo_end = (vaddr_t)bootinfo_next(bi);
+
+	/*
+	 * If we have a RAM disk, we need to take it out of the
+	 * available memory segments.
+	 */
+	bootinfo_reserve_initrd();
 }
 
 /*
@@ -287,10 +373,34 @@ void
 bootinfo_setup_initrd(void)
 {
 #ifdef MEMORY_DISK_DYNAMIC
-	struct bi_record *bi = bootinfo_find(BI_RAMDISK);
-	if (bi != NULL) {
-		struct bi_mem_info *rd = bootinfo_dataptr(bi);
-		md_root_setconf((void *)rd->mem_addr, rd->mem_size);
+	if (bootinfo_initrd_size != 0) {
+		paddr_t rdstart, rdend, rdpgoff;
+		vaddr_t rdva, rdoff;
+		vsize_t rdvsize;
+
+		printf("Initializing root RAM disk @ %p - %p\n",
+		    (void *)bootinfo_initrd_start,
+		    (void *)(bootinfo_initrd_start + bootinfo_initrd_size - 1));
+
+		rdend = m68k_round_page(bootinfo_initrd_start +
+		    bootinfo_initrd_size);
+		rdstart = m68k_trunc_page(bootinfo_initrd_start);
+		rdvsize = rdend - rdstart;
+		rdpgoff = bootinfo_initrd_start & PAGE_MASK;
+
+		rdva = uvm_km_alloc(kernel_map, rdvsize, PAGE_SIZE,
+		    UVM_KMF_VAONLY);
+		if (rdva == 0) {
+			printf("WARNING: Unable to allocate KVA for "
+			       "RAM disk.\n");
+			return;
+		}
+		for (rdoff = 0; rdoff < rdvsize; rdoff += PAGE_SIZE) {
+			pmap_kenter_pa(rdva + rdoff, rdstart + rdoff,
+			    VM_PROT_READ | VM_PROT_WRITE, 0);
+		}
+		md_root_setconf((void *)(rdva + rdpgoff),
+		    bootinfo_initrd_size);
 	}
 #endif /* MEMORY_DISK_DYNAMIC */
 }
Index: src/sys/arch/virt68k/virt68k/machdep.c
diff -u src/sys/arch/virt68k/virt68k/machdep.c:1.3 src/sys/arch/virt68k/virt68k/machdep.c:1.4
--- src/sys/arch/virt68k/virt68k/machdep.c:1.3	Tue Jan  2 18:10:36 2024
+++ src/sys/arch/virt68k/virt68k/machdep.c	Sat Jan  6 17:32:41 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.3 2024/01/02 18:10:36 thorpej Exp $	*/
+/*	$NetBSD: machdep.c,v 1.4 2024/01/06 17:32:41 thorpej Exp $	*/
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.3 2024/01/02 18:10:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.4 2024/01/06 17:32:41 thorpej Exp $");
 
 #include "opt_ddb.h"
 #include "opt_m060sp.h"
@@ -171,7 +171,7 @@ virt68k_init(void)
 	/*
 	 * Tell the VM system about available physical memory.
 	 */
-	for (i = 0; i < bootinfo_mem_nsegments; i++) {
+	for (i = 0; i < bootinfo_mem_nsegments_avail; i++) {
 		if (bootinfo_mem_segments_avail[i].mem_size < PAGE_SIZE) {
 			/*
 			 * Segment has been completely gobbled up.

Reply via email to