patch-2.4.0-test2 linux/arch/alpha/kernel/setup.c

Next file: linux/arch/alpha/kernel/signal.c
Previous file: linux/arch/alpha/kernel/ptrace.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test1/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
@@ -34,6 +34,15 @@
 #include <linux/blk.h>
 #endif
 
+#include <linux/notifier.h>
+extern struct notifier_block *panic_notifier_list;
+static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
+static struct notifier_block alpha_panic_block = {
+	alpha_panic_event,
+        NULL,
+        INT_MAX /* try to do it first */
+};
+
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -42,6 +51,7 @@
 #include <asm/io.h>
 #include <asm/pci.h>
 #include <asm/mmu_context.h>
+#include <asm/console.h>
 
 #include "proto.h"
 #include "pci_impl.h"
@@ -53,6 +63,17 @@
 /* Which processor we booted from.  */
 int boot_cpuid;
 
+/* Using SRM callbacks for initial console output. This works from
+   setup_arch() time through the end of init_IRQ(), as those places
+   are under our control.
+
+   By default, OFF; set it with a bootcommand arg of "srmcons".
+*/
+int srmcons_output = 0;
+
+/* Enforce a memory size limit; useful for testing. By default, none. */
+unsigned long mem_size_limit = 0;
+
 #ifdef CONFIG_ALPHA_GENERIC
 struct alpha_machine_vector alpha_mv;
 int alpha_using_srm;
@@ -139,6 +160,7 @@
 WEAK(noritake_primo_mv);
 WEAK(p2k_mv);
 WEAK(pc164_mv);
+WEAK(privateer_mv);
 WEAK(rawhide_mv);
 WEAK(ruffian_mv);
 WEAK(rx164_mv);
@@ -147,6 +169,7 @@
 WEAK(sx164_mv);
 WEAK(takara_mv);
 WEAK(webbrick_mv);
+WEAK(wildfire_mv);
 WEAK(xl_mv);
 WEAK(xlt_mv);
 
@@ -202,14 +225,33 @@
 	for ((cluster) = (memdesc)->cluster, (i) = 0;		\
 	     (i) < (memdesc)->numclusters; (i)++, (cluster)++)
 
+static unsigned long __init
+get_mem_size_limit(char *s)
+{
+        unsigned long end = 0;
+        char *from = s;
+
+        end = simple_strtoul(from, &from, 0);
+        if ( *from == 'K' || *from == 'k' ) {
+                end = end << 10;
+                from++;
+        } else if ( *from == 'M' || *from == 'm' ) {
+                end = end << 20;
+                from++;
+        } else if ( *from == 'G' || *from == 'g' ) {
+                end = end << 30;
+                from++;
+        }
+        return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
+}
+
 static void __init
-setup_memory(void)
+setup_memory(void * kernel_end)
 {
 	struct memclust_struct * cluster;
 	struct memdesc_struct * memdesc;
 	unsigned long start_pfn, bootmap_size, bootmap_pages, bootmap_start;
 	unsigned long start, end;
-	extern char _end[];
 	int i;
 
 	/* Find free clusters, and init and free the bootmem accordingly.  */
@@ -232,15 +274,23 @@
 			max_low_pfn = end;
 	}
 
-	/* Find the end of the kernel memory.  */
-	start_pfn = PFN_UP(virt_to_phys(_end));
+	if (mem_size_limit && max_low_pfn >= mem_size_limit)
+	{
+		printk("setup: forcing memory size to %ldK (from %ldK).\n",
+		       mem_size_limit << (PAGE_SHIFT - 10),
+		       max_low_pfn    << (PAGE_SHIFT - 10));
+		max_low_pfn = mem_size_limit;
+	}
+
+	/* Find the end of the memory used by the kernel.  */
+	start_pfn = PFN_UP(virt_to_phys(kernel_end));
 	bootmap_start = -1;
 
  try_again:
 	if (max_low_pfn <= start_pfn)
 		panic("not enough memory to boot");
 
-	/* We need to know how many physically contigous pages
+	/* We need to know how many physically contiguous pages
 	   we'll need for the bootmap.  */
 	bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
 
@@ -307,14 +357,14 @@
 		printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
 		       (void *) initrd_start, INITRD_SIZE);
 
-		if (initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
+		if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
 			printk("initrd extends beyond end of memory "
-			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			       "(0x%08lx > 0x%p)\ndisabling initrd\n",
 			       initrd_end,
 			       phys_to_virt(PFN_PHYS(max_low_pfn)));
 			initrd_start = initrd_end = 0;
 		} else {
-			reserve_bootmem(virt_to_phys(initrd_start),
+			reserve_bootmem(virt_to_phys((void *)initrd_start),
 					INITRD_SIZE);
 		}
 	}
@@ -346,20 +396,98 @@
 #undef PFN_PHYS
 #undef PFN_MAX
 
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+/*
+ *      Manage the SRM callbacks as a "console".
+ */
+static struct console srmcons;
+
+void __init register_srm_console(void)
+{
+        register_console(&srmcons);
+}
+
+void __init unregister_srm_console(void)
+{
+        unregister_console(&srmcons);
+}
+
+static void srm_console_write(struct console *co, const char *s,
+                                unsigned count)
+{
+	srm_printk(s);
+}
+
+static kdev_t srm_console_device(struct console *c)
+{
+  /* Huh? */
+        return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int srm_console_wait_key(struct console *co)
+{
+  /* Huh? */
+	return 1;
+}
+
+static int __init srm_console_setup(struct console *co, char *options)
+{
+	return 1;
+}
+
+static struct console srmcons = {
+        "srm0",
+        srm_console_write,
+        NULL,
+        srm_console_device,
+        srm_console_wait_key,
+        NULL,
+	srm_console_setup,
+        CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
+        -1,
+        0,
+        NULL
+};
+
+#else
+void __init register_srm_console(void)
+{
+}
+void __init unregister_srm_console(void)
+{
+}
+#endif
+
 void __init
 setup_arch(char **cmdline_p)
 {
 	struct alpha_machine_vector *vec = NULL;
 	struct percpu_struct *cpu;
 	char *type_name, *var_name, *p;
+	extern char _end;
+	void * kernel_end = &_end; /* end of kernel */
 
 	hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
 	boot_cpuid = hard_smp_processor_id();
 
+	/* Register a call for panic conditions. */
+	notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
+
+#ifdef CONFIG_ALPHA_GENERIC
+	/* Assume that we've booted from SRM if we havn't booted from MILO.
+	   Detect the later by looking for "MILO" in the system serial nr.  */
+	alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#endif
+
+	/* If we are using SRM, we want to allow callbacks
+	   as early as possible, so do this NOW, and then
+	   they should work immediately thereafter.
+	*/
+	kernel_end = callback_init(kernel_end);
+
 	/* 
 	 * Locate the command line.
 	 */
-
 	/* Hack for Jensen... since we're restricted to 8 or 16 chars for
 	   boot flags depending on the boot mode, we need some shorthand.
 	   This should do for installation.  */
@@ -375,7 +503,6 @@
 	/* 
 	 * Process command-line arguments.
 	 */
-
 	for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
 		if (strncmp(p, "alpha_mv=", 9) == 0) {
 			vec = get_sysvec_byname(p+9);
@@ -385,15 +512,27 @@
 			est_cycle_freq = simple_strtol(p+6, NULL, 0);
 			continue;
 		}
+		if (strncmp(p, "mem=", 4) == 0) {
+			mem_size_limit = get_mem_size_limit(p+4);
+			continue;
+		}
+		if (strncmp(p, "srmcons", 7) == 0) {
+			srmcons_output = 1;
+			continue;
+		}
 	}
 
-	/* Replace the command line, not that we've killed it with strtok.  */
+	/* Replace the command line, now that we've killed it with strtok.  */
 	strcpy(command_line, saved_command_line);
 
+	/* If we want SRM console printk echoing early, do it now. */
+	if (alpha_using_srm && srmcons_output) {
+		register_srm_console();
+	}
+
 	/*
 	 * Indentify and reconfigure for the current system.
 	 */
-
 	get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
 		     &type_name, &var_name);
 	if (*var_name == '0')
@@ -415,12 +554,6 @@
 		alpha_mv = *vec;
 	}
 	
-#ifdef CONFIG_ALPHA_GENERIC
-	/* Assume that we've booted from SRM if we havn't booted from MILO.
-	   Detect the later by looking for "MILO" in the system serial nr.  */
-	alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#endif
-
 	printk("Booting "
 #ifdef CONFIG_ALPHA_GENERIC
 	       "GENERIC "
@@ -433,10 +566,9 @@
 	printk("Command line: %s\n", command_line);
 
 	/* 
-	 * Sync with the HAE
+	 * Sync up the HAE.
+	 * Save the SRM's current value for restoration.
 	 */
-
-	/* Save the SRM's current value for restoration.  */
 	srm_hae = *alpha_mv.hae_register;
 	__set_hae(alpha_mv.hae_cache);
 
@@ -444,7 +576,7 @@
 	wrmces(0x7);
 
 	/* Find our memory.  */
-	setup_memory();
+	setup_memory(kernel_end);
 
 	/* Initialize the machine.  Usually has to do with setting up
 	   DMA windows and the like.  */
@@ -499,7 +631,7 @@
 	"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
 	"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
 	"Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
-	"Tsunami", "Wildfire", "CUSCO", "Eiger"
+	"Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan"
 };
 
 static char unofficial_names[][8] = {"100", "Ruffian"};
@@ -523,6 +655,11 @@
 };
 static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
 
+static char titan_names[][16] = {
+	"0", "Privateer"
+};
+static int titan_indices[] = {0,1};
+
 static char tsunami_names[][16] = {
 	"0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
 	"Goldrush", "Webbrick", "Catamaran"
@@ -569,9 +706,10 @@
 		&takara_mv,
 		NULL,		/* Yukon */
 		NULL,		/* Tsunami -- see variation.  */
-		NULL,		/* Wildfire */
+		&wildfire_mv,	/* Wildfire */
 		NULL,		/* CUSCO */
 		&eiger_mv,	/* Eiger */
+		NULL,		/* Titan */
 	};
 
 	static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
@@ -609,6 +747,12 @@
 		&eb66p_mv
 	};
 
+	static struct alpha_machine_vector *titan_vecs[] __initlocaldata =
+	{
+		NULL,
+		&privateer_mv,		/* privateer */
+	};
+
 	static struct alpha_machine_vector *tsunami_vecs[]  __initlocaldata =
 	{
 		NULL,
@@ -665,6 +809,10 @@
 			if (member < N(eb66_indices))
 				vec = eb66_vecs[eb66_indices[member]];
 			break;
+		case ST_DEC_TITAN:
+			if (member < N(titan_indices))
+				vec = titan_vecs[titan_indices[member]];
+			break;
 		case ST_DEC_TSUNAMI:
 			if (member < N(tsunami_indices))
 				vec = tsunami_vecs[tsunami_indices[member]];
@@ -723,6 +871,7 @@
 		&noritake_primo_mv,
 		&p2k_mv,
 		&pc164_mv,
+		&privateer_mv,
 		&rawhide_mv,
 		&ruffian_mv,
 		&rx164_mv,
@@ -731,6 +880,7 @@
 		&sx164_mv,
 		&takara_mv,
 		&webbrick_mv,
+		&wildfire_mv,
 		&xl_mv,
 		&xlt_mv
 	};
@@ -801,6 +951,10 @@
 		if (member < N(rawhide_indices))
 			*variation_name = rawhide_names[rawhide_indices[member]];
 		break;
+	case ST_DEC_TITAN:
+		if (member < N(titan_indices))
+			*variation_name = titan_names[titan_indices[member]];
+		break;
 	case ST_DEC_TSUNAMI:
 		if (member < N(tsunami_indices))
 			*variation_name = tsunami_names[tsunami_indices[member]];
@@ -873,7 +1027,7 @@
 
 	static char cpu_names[][8] = {
 		"EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
-		"EV6", "PCA56", "PCA57", "EV67"
+		"EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL"
 	};
 
 	struct percpu_struct *cpu;
@@ -935,4 +1089,17 @@
 #endif
 
 	return len;
+}
+
+static int alpha_panic_event(struct notifier_block *this,
+			     unsigned long event,
+			     void *ptr)
+{
+#if 1
+	/* FIXME FIXME FIXME */
+	/* If we are using SRM and serial console, just hard halt here. */
+	if (alpha_using_srm && srmcons_output)
+		__halt();
+#endif
+        return NOTIFY_DONE;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)