Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/alpha Qemu loads the kernel directly, and so there'...



details:   https://anonhg.NetBSD.org/src/rev/ea9bc70cf163
branches:  trunk
changeset: 944556:ea9bc70cf163
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Oct 03 17:31:46 2020 +0000

description:
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.

diffstat:

 sys/arch/alpha/alpha/autoconf.c |  57 ++++++++++++++++++++++++++++++++++++++--
 sys/arch/alpha/alpha/machdep.c  |  39 ++++++++++++++++++++++-----
 sys/arch/alpha/alpha/prom.c     |  56 ++++++++++++++++++++++++++++++++++++++-
 sys/arch/alpha/include/alpha.h  |   3 +-
 sys/arch/alpha/include/prom.h   |  10 ++++++-
 5 files changed, 150 insertions(+), 15 deletions(-)

diffs (297 lines):

diff -r d54bd3dc2a6f -r ea9bc70cf163 sys/arch/alpha/alpha/autoconf.c
--- a/sys/arch/alpha/alpha/autoconf.c   Sat Oct 03 17:30:54 2020 +0000
+++ b/sys/arch/alpha/alpha/autoconf.c   Sat Oct 03 17:31:46 2020 +0000
@@ -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 @@
        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();
 }
 
diff -r d54bd3dc2a6f -r ea9bc70cf163 sys/arch/alpha/alpha/machdep.c
--- a/sys/arch/alpha/alpha/machdep.c    Sat Oct 03 17:30:54 2020 +0000
+++ b/sys/arch/alpha/alpha/machdep.c    Sat Oct 03 17:31:46 2020 +0000
@@ -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 @@
                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 @@
        }
 }
 
+void   (*alpha_delay_fn)(unsigned long);
+
 /*
  * Wait "n" microseconds.
  */
@@ -1613,6 +1627,15 @@
        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;
diff -r d54bd3dc2a6f -r ea9bc70cf163 sys/arch/alpha/alpha/prom.c
--- a/sys/arch/alpha/alpha/prom.c       Sat Oct 03 17:30:54 2020 +0000
+++ b/sys/arch/alpha/alpha/prom.c       Sat Oct 03 17:31:46 2020 +0000
@@ -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 @@
 
 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 @@
        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 @@
        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
diff -r d54bd3dc2a6f -r ea9bc70cf163 sys/arch/alpha/include/alpha.h
--- a/sys/arch/alpha/include/alpha.h    Sat Oct 03 17:30:54 2020 +0000
+++ b/sys/arch/alpha/include/alpha.h    Sat Oct 03 17:31:46 2020 +0000
@@ -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 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 */
diff -r d54bd3dc2a6f -r ea9bc70cf163 sys/arch/alpha/include/prom.h
--- a/sys/arch/alpha/include/prom.h     Sat Oct 03 17:30:54 2020 +0000
+++ b/sys/arch/alpha/include/prom.h     Sat Oct 03 17:31:46 2020 +0000
@@ -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 @@
        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   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);



Home | Main Index | Thread Index | Old Index