Module Name:    src
Committed By:   thorpej
Date:           Sat Oct  3 17:31:46 UTC 2020

Modified Files:
        src/sys/arch/alpha/alpha: autoconf.c machdep.c prom.c
        src/sys/arch/alpha/include: alpha.h prom.h

Log Message:
Qemu loads the kernel directly, and so there's no bootloader to provide
a "bootinfo" structure for us.  Qemu does, however, place a Linux kernel
parameter block at kernel_text[] - 0x6000 that contains Linux-style kernel
command line arguments.  So, add a prom_qemu_getenv() that allows us to
look for specific things passed along to the kernel from there, and use
them as follows:

- Support specifying the root device in the forms "root=/dev/wd0a",
  "root=wd0a", or "rootdev=wd0".
- Support SRM-like -flags ... in the form of "flags=AD".  In the case of
  Qemu, we also assume that no flags=... is the same as "flags=A", i.e.
  perform an auto-boot.

Also allow an alternate delay() function to be specified, if the platform
wishes to provide one.


To generate a diff of this commit:
cvs rdiff -u -r1.54 -r1.55 src/sys/arch/alpha/alpha/autoconf.c
cvs rdiff -u -r1.365 -r1.366 src/sys/arch/alpha/alpha/machdep.c
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/alpha/alpha/prom.c
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/alpha/include/alpha.h
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/alpha/include/prom.h

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/alpha/alpha/autoconf.c
diff -u src/sys/arch/alpha/alpha/autoconf.c:1.54 src/sys/arch/alpha/alpha/autoconf.c:1.55
--- src/sys/arch/alpha/alpha/autoconf.c:1.54	Mon Sep  3 16:29:22 2018
+++ src/sys/arch/alpha/alpha/autoconf.c	Sat Oct  3 17:31:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: autoconf.c,v 1.54 2018/09/03 16:29:22 riastradh Exp $ */
+/* $NetBSD: autoconf.c,v 1.55 2020/10/03 17:31:46 thorpej Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -42,7 +42,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.54 2018/09/03 16:29:22 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.55 2020/10/03 17:31:46 thorpej Exp $");
 
 #include "pci.h"
 
@@ -97,13 +97,64 @@ cpu_configure(void)
 	hwrpb_restart_setup();
 }
 
+static void
+qemu_find_rootdev(void)
+{
+	char buf[32];
+
+	/*
+	 * Check for "rootdev=wd0".
+	 */
+	if (prom_qemu_getenv("rootdev", buf, sizeof(buf))) {
+		snprintf(bootinfo.booted_dev, sizeof(bootinfo.booted_dev),
+		    "rootdev=%s", buf);
+		booted_device = device_find_by_xname(buf);
+		return;
+	}
+
+	/*
+	 * Check for "root=/dev/wd0a", "root=/dev/hda1", etc.
+	 */
+	if (prom_qemu_getenv("root", buf, sizeof(buf))) {
+		const size_t devlen = strlen("/dev/");
+		const char *cp = buf;
+		char *ecp = &buf[sizeof(buf) - 1];
+
+		snprintf(bootinfo.booted_dev, sizeof(bootinfo.booted_dev),
+		    "root=%s", buf);
+
+		/* Find the start of the device xname. */
+		if (strlen(cp) > devlen && strncmp(cp, "/dev/", devlen) == 0) {
+			cp += devlen;
+		}
+
+		/* Now strip any partition letter off the end. */
+		while (ecp != cp) {
+			if (*ecp >= '0' && *ecp <= '9') {
+				break;
+			}
+			*ecp-- = '\0';
+		}
+
+		booted_device = device_find_by_xname(cp);
+		return;
+	}
+
+	printf("WARNING: no rootdev= or root= arguments provided by Qemu\n");
+}
+
 void
 cpu_rootconf(void)
 {
 
-	if (booted_device == NULL)
+	if (booted_device == NULL && alpha_is_qemu) {
+		qemu_find_rootdev();
+	}
+
+	if (booted_device == NULL) {
 		printf("WARNING: can't figure what device matches \"%s\"\n",
 		    bootinfo.booted_dev);
+	}
 	rootconf();
 }
 

Index: src/sys/arch/alpha/alpha/machdep.c
diff -u src/sys/arch/alpha/alpha/machdep.c:1.365 src/sys/arch/alpha/alpha/machdep.c:1.366
--- src/sys/arch/alpha/alpha/machdep.c:1.365	Sun Sep 27 23:16:10 2020
+++ src/sys/arch/alpha/alpha/machdep.c	Sat Oct  3 17:31:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.365 2020/09/27 23:16:10 thorpej Exp $ */
+/* $NetBSD: machdep.c,v 1.366 2020/10/03 17:31:46 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2019 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.365 2020/09/27 23:16:10 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.366 2020/10/03 17:31:46 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -320,12 +320,24 @@ nobootinfo:
 		bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys;
 		bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size;
 		init_prom_interface(ptb, (struct rpb *)HWRPB_ADDR);
-		prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
-		    sizeof bootinfo.boot_flags);
-		prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
-		    sizeof bootinfo.booted_kernel);
-		prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
-		    sizeof bootinfo.booted_dev);
+		if (alpha_is_qemu) {
+			/*
+			 * Grab boot flags from kernel command line.
+			 * Assume autoboot if not supplied.
+			 */
+			if (! prom_qemu_getenv("flags", bootinfo.boot_flags,
+					       sizeof(bootinfo.boot_flags))) {
+				strlcpy(bootinfo.boot_flags, "A",
+					sizeof(bootinfo.boot_flags));
+			}
+		} else {
+			prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
+			    sizeof bootinfo.boot_flags);
+			prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
+			    sizeof bootinfo.booted_kernel);
+			prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
+			    sizeof bootinfo.booted_dev);
+		}
 	}
 
 	/*
@@ -1602,6 +1614,8 @@ setregs(register struct lwp *l, struct e
 	}
 }
 
+void	(*alpha_delay_fn)(unsigned long);
+
 /*
  * Wait "n" microseconds.
  */
@@ -1613,6 +1627,15 @@ delay(unsigned long n)
 	if (n == 0)
 		return;
 
+	/*
+	 * If we have an alternative delay function, go ahead and
+	 * use it.
+	 */
+	if (alpha_delay_fn != NULL) {
+		(*alpha_delay_fn)(n);
+		return;
+	}
+
 	pcc0 = alpha_rpcc() & 0xffffffffUL;
 	cycles = 0;
 	usec = 0;

Index: src/sys/arch/alpha/alpha/prom.c
diff -u src/sys/arch/alpha/alpha/prom.c:1.57 src/sys/arch/alpha/alpha/prom.c:1.58
--- src/sys/arch/alpha/alpha/prom.c:1.57	Sun Sep 27 23:16:10 2020
+++ src/sys/arch/alpha/alpha/prom.c	Sat Oct  3 17:31:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: prom.c,v 1.57 2020/09/27 23:16:10 thorpej Exp $ */
+/* $NetBSD: prom.c,v 1.58 2020/10/03 17:31:46 thorpej Exp $ */
 
 /*
  * Copyright (c) 1992, 1994, 1995, 1996 Carnegie Mellon University
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: prom.c,v 1.57 2020/09/27 23:16:10 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: prom.c,v 1.58 2020/10/03 17:31:46 thorpej Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -64,6 +64,8 @@ int		prom_mapped = 1;	/* Is PROM still m
 
 static kmutex_t	prom_lock;
 
+static struct linux_kernel_params qemu_kernel_params;
+
 #ifdef _PROM_MAY_USE_PROM_CONSOLE
 
 pt_entry_t	prom_pte, saved_pte[1];	/* XXX */
@@ -137,6 +139,21 @@ init_prom_interface(u_long ptb_pfn, stru
 	prom_dispatch_v.routine_arg = c->crb_v_dispatch;
 	prom_dispatch_v.routine = c->crb_v_dispatch->entry_va;
 
+	if (alpha_is_qemu) {
+		/*
+		 * Qemu has placed a Linux kernel parameter block
+		 * at kernel_text[] - 0x6000.  We ensure the command
+		 * line field is always NUL-terminated to simplify
+		 * things later.
+		 */
+		extern char kernel_text[];
+		memcpy(&qemu_kernel_params,
+		       (void *)((vaddr_t)kernel_text - 0x6000),
+		       sizeof(qemu_kernel_params));
+		qemu_kernel_params.kernel_cmdline[
+		    sizeof(qemu_kernel_params.kernel_cmdline) - 1] = '\0';
+	}
+
 #ifdef _PROM_MAY_USE_PROM_CONSOLE
 	if (prom_uses_prom_console()) {
 		/*
@@ -170,6 +187,41 @@ init_bootstrap_console(void)
 	cn_tab = &promcons;
 }
 
+bool
+prom_qemu_getenv(const char *var, char *buf, size_t buflen)
+{
+	const size_t varlen = strlen(var);
+	const char *sp;
+
+	if (!alpha_is_qemu) {
+		return false;
+	}
+
+	sp = qemu_kernel_params.kernel_cmdline;
+	for (;;) {
+		sp = strstr(sp, var);
+		if (sp == NULL) {
+			return false;
+		}
+		sp += varlen;
+		if (*sp++ != '=') {
+			continue;
+		}
+		/* Found it. */
+		break;
+	}
+
+	while (--buflen) {
+		if (*sp == ' ' || *sp == '\t' || *sp == '\0') {
+			break;
+		}
+		*buf++ = *sp++;
+	}
+	*buf = '\0';
+
+	return true;
+}
+
 #ifdef _PROM_MAY_USE_PROM_CONSOLE
 static void prom_cache_sync(void);
 #endif

Index: src/sys/arch/alpha/include/alpha.h
diff -u src/sys/arch/alpha/include/alpha.h:1.41 src/sys/arch/alpha/include/alpha.h:1.42
--- src/sys/arch/alpha/include/alpha.h:1.41	Sun Sep 27 23:16:10 2020
+++ src/sys/arch/alpha/include/alpha.h	Sat Oct  3 17:31:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: alpha.h,v 1.41 2020/09/27 23:16:10 thorpej Exp $ */
+/* $NetBSD: alpha.h,v 1.42 2020/10/03 17:31:46 thorpej Exp $ */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -73,6 +73,7 @@ extern u_long cpu_amask;		/* from AMASK 
 extern int bootdev_debug;
 extern int alpha_fp_sync_complete;
 extern int alpha_unaligned_print, alpha_unaligned_fix, alpha_unaligned_sigbus;
+extern void (*alpha_delay_fn)(unsigned long);
 
 void	XentArith(uint64_t, uint64_t, uint64_t);	/* MAGIC */
 void	XentIF(uint64_t, uint64_t, uint64_t);		/* MAGIC */

Index: src/sys/arch/alpha/include/prom.h
diff -u src/sys/arch/alpha/include/prom.h:1.15 src/sys/arch/alpha/include/prom.h:1.16
--- src/sys/arch/alpha/include/prom.h:1.15	Thu Sep  3 02:09:09 2020
+++ src/sys/arch/alpha/include/prom.h	Sat Oct  3 17:31:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: prom.h,v 1.15 2020/09/03 02:09:09 thorpej Exp $ */
+/* $NetBSD: prom.h,v 1.16 2020/10/03 17:31:46 thorpej Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -46,6 +46,13 @@ typedef union {
 	uint64_t bits;
 } prom_return_t;
 
+/* Linux kernel parameter block filled out by Qemu. */
+struct linux_kernel_params {
+	char		kernel_cmdline[256];
+	uint64_t	initrd_base;
+	uint64_t	initrd_size;
+};
+
 #ifdef _STANDALONE
 int	getchar(void);
 void	putchar(int);
@@ -53,6 +60,7 @@ void	putchar(int);
 
 void	prom_halt(int) __attribute__((__noreturn__));
 int	prom_getenv(int, char *, int);
+bool	prom_qemu_getenv(const char *, char *, size_t);
 
 void	hwrpb_primary_init(void);
 void	hwrpb_restart_setup(void);

Reply via email to