changeset 4050:9349e27b46cc onnv_63

6479998 CPU DR should not panic the system on memory allocation failure
author jb145095
date Mon, 16 Apr 2007 22:09:13 -0700
parents 1799c30fb70c
children f133c2050317
files usr/src/uts/sun4/os/mp_startup.c usr/src/uts/sun4/os/startup.c usr/src/uts/sun4u/os/mach_mp_startup.c usr/src/uts/sun4u/os/mach_startup.c usr/src/uts/sun4v/os/intrq.c usr/src/uts/sun4v/os/mach_mp_startup.c
diffstat 6 files changed, 125 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sun4/os/mp_startup.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4/os/mp_startup.c	Mon Apr 16 22:09:13 2007 -0700
@@ -46,7 +46,7 @@
 #endif /* TRAPTRACE */
 #include <sys/cpu_sgnblk_defs.h>
 
-extern void cpu_intrq_setup(struct cpu *);
+extern int cpu_intrq_setup(struct cpu *);
 extern void cpu_intrq_cleanup(struct cpu *);
 extern void cpu_intrq_register(struct cpu *);
 
@@ -280,7 +280,7 @@
 /*
  * Routine to set up a CPU to prepare for starting it up.
  */
-void
+int
 setup_cpu_common(int cpuid)
 {
 	struct cpu *cp = NULL;
@@ -292,6 +292,7 @@
 #endif /* TRAPTRACE */
 
 	extern void idle();
+	int	rval;
 
 	ASSERT(MUTEX_HELD(&cpu_lock));
 	ASSERT(cpu[cpuid] == NULL);
@@ -419,13 +420,16 @@
 	if (nosteal_nsec == -1)
 		cmp_set_nosteal_interval();
 
-	cpu_intrq_setup(cp);
+	if ((rval = cpu_intrq_setup(cp)) != 0) {
+		return (rval);
+	}
 
 	/*
 	 * Initialize MMU context domain information.
 	 */
 	sfmmu_cpu_init(cp);
 
+	return (0);
 }
 
 /*
@@ -450,8 +454,10 @@
 	cpu_uninit_private(cp);
 
 	/* Free cpu ID string and brand string. */
-	kmem_free(cp->cpu_idstr, strlen(cp->cpu_idstr) + 1);
-	kmem_free(cp->cpu_brandstr, strlen(cp->cpu_brandstr) + 1);
+	if (cp->cpu_idstr)
+		kmem_free(cp->cpu_idstr, strlen(cp->cpu_idstr) + 1);
+	if (cp->cpu_brandstr)
+		kmem_free(cp->cpu_brandstr, strlen(cp->cpu_brandstr) + 1);
 
 	cpu_vm_data_destroy(cp);
 
@@ -512,7 +518,8 @@
 	 */
 	disp_cpu_fini(cp);
 	cpu_pa[cpuid] = 0;
-	sfmmu_cpu_cleanup(cp);
+	if (CPU_MMU_CTXP(cp))
+		sfmmu_cpu_cleanup(cp);
 	bzero(cp, sizeof (*cp));
 
 	/*
@@ -651,11 +658,6 @@
 
 extern struct cpu	*cpu[NCPU];	/* pointers to all CPUs */
 
-extern void setup_cpu_common(int);
-extern void common_startup_init(cpu_t *, int);
-extern void start_cpu(int, void(*func)(int));
-extern void cold_flag_set(int cpuid);
-
 /*
  * cpu_bringup_set is a tunable (via /etc/system, debugger, etc.) that
  * can be used during debugging to control which processors are brought
@@ -752,7 +754,9 @@
 
 		ASSERT(cpu[cpuid] == NULL);
 
-		setup_cpu_common(cpuid);
+		if (setup_cpu_common(cpuid)) {
+			cmn_err(CE_PANIC, "cpu%d: setup failed", cpuid);
+		}
 
 		common_startup_init(cpu[cpuid], cpuid);
 
--- a/usr/src/uts/sun4/os/startup.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4/os/startup.c	Mon Apr 16 22:09:13 2007 -0700
@@ -67,7 +67,7 @@
 #include <sys/mmu.h>
 
 extern void setup_trap_table(void);
-extern void cpu_intrq_setup(struct cpu *);
+extern int cpu_intrq_setup(struct cpu *);
 extern void cpu_intrq_register(struct cpu *);
 extern void contig_mem_init(void);
 extern void mach_dump_buffer_init(void);
@@ -2320,7 +2320,10 @@
 	 */
 	contig_mem_init();
 	mach_descrip_init();
-	cpu_intrq_setup(CPU);
+
+	if (cpu_intrq_setup(CPU)) {
+		cmn_err(CE_PANIC, "cpu%d: setup failed", CPU->cpu_id);
+	}
 	cpu_intrq_register(CPU);
 	mach_htraptrace_setup(CPU->cpu_id);
 	mach_htraptrace_configure(CPU->cpu_id);
--- a/usr/src/uts/sun4u/os/mach_mp_startup.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4u/os/mach_mp_startup.c	Mon Apr 16 22:09:13 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -154,7 +153,7 @@
 mp_cpu_configure(int cpuid)
 {
 	extern void fill_cpu_ddi(dev_info_t *);
-	extern void setup_cpu_common(int);
+	extern int setup_cpu_common(int);
 	struct mp_find_cpu_arg target;
 
 	ASSERT(MUTEX_HELD(&cpu_lock));
@@ -172,7 +171,11 @@
 	 */
 	fill_cpu_ddi(target.dip);
 
-	setup_cpu_common(cpuid);
+	/*
+	 * sun4v cpu setup may fail. sun4u assumes cpu setup to
+	 * be always successful, so the return value is ignored.
+	 */
+	(void) setup_cpu_common(cpuid);
 
 	return (0);
 }
--- a/usr/src/uts/sun4u/os/mach_startup.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4u/os/mach_startup.c	Mon Apr 16 22:09:13 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -394,10 +394,11 @@
 }
 
 /*ARGSUSED*/
-void
+int
 cpu_intrq_setup(struct cpu *cp)
 {
 	/* Interrupt mondo queues not applicable to sun4u */
+	return (0);
 }
 
 /*ARGSUSED*/
--- a/usr/src/uts/sun4v/os/intrq.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4v/os/intrq.c	Mon Apr 16 22:09:13 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,40 +58,32 @@
 	ret = hv_cpu_qconf(CPU_NRQ, mcpup->cpu_nrq_base_pa, cpu_nrq_entries);
 	if (ret != H_EOK)
 		cmn_err(CE_PANIC, "cpu%d: non-resumable error queue "
-		    "configuration failed, error %lu", cpu->cpu_id, ret);
+			"configuration failed, error %lu", cpu->cpu_id, ret);
 }
 
-void
+int
 cpu_intrq_setup(struct cpu *cpu)
 {
 	struct machcpu *mcpup = &cpu->cpu_m;
-	int cpu_list_size;
-	uint64_t cpu_q_size;
-	uint64_t dev_q_size;
-	uint64_t cpu_rq_size;
-	uint64_t cpu_nrq_size;
+	size_t size;
+
+	/*
+	 * This routine will return with an error return if any
+	 * contig_mem_alloc() fails.  It is expected that the caller will
+	 * call cpu_intrq_cleanup() (or cleanup_cpu_common() which will).
+	 * That will cleanly free only those blocks that were alloc'd.
+	 */
 
 	/*
 	 * Allocate mondo data for xcalls.
 	 */
 	mcpup->mondo_data = contig_mem_alloc(INTR_REPORT_SIZE);
-	if (mcpup->mondo_data == NULL)
-		cmn_err(CE_PANIC, "cpu%d: cpu mondo_data allocation failed",
-		    cpu->cpu_id);
 
-	/*
-	 *  Allocate a percpu list of NCPU for xcalls
-	 */
-	cpu_list_size = NCPU * sizeof (uint16_t);
-	if (cpu_list_size < INTR_REPORT_SIZE)
-		cpu_list_size = INTR_REPORT_SIZE;
-
-	mcpup->cpu_list = contig_mem_alloc(cpu_list_size);
-	if (mcpup->cpu_list == NULL)
-		cmn_err(CE_PANIC, "cpu%d: cpu cpu_list allocation failed",
-		    cpu->cpu_id);
-	mcpup->cpu_list_ra = va_to_pa(mcpup->cpu_list);
-
+	if (mcpup->mondo_data == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: cpu mondo_data allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
 	/*
 	 * va_to_pa() is too expensive to call for every crosscall
 	 * so we do it here at init time and save it in machcpu.
@@ -99,45 +91,86 @@
 	mcpup->mondo_data_ra = va_to_pa(mcpup->mondo_data);
 
 	/*
+	 *  Allocate a percpu list of NCPU for xcalls
+	 */
+	size = NCPU * sizeof (uint16_t);
+	if (size < INTR_REPORT_SIZE)
+		size = INTR_REPORT_SIZE;
+
+	mcpup->cpu_list = contig_mem_alloc(size);
+
+	if (mcpup->cpu_list == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: cpu cpu_list allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
+	mcpup->cpu_list_ra = va_to_pa(mcpup->cpu_list);
+
+	/*
 	 * Allocate sun4v interrupt and error queues.
 	 */
-	cpu_q_size = cpu_q_entries * INTR_REPORT_SIZE;
-	mcpup->cpu_q_va = contig_mem_alloc(cpu_q_size);
-	if (mcpup->cpu_q_va == NULL)
-		cmn_err(CE_PANIC, "cpu%d: cpu intrq allocation failed",
-		    cpu->cpu_id);
+	size = cpu_q_entries * INTR_REPORT_SIZE;
+
+	mcpup->cpu_q_va = contig_mem_alloc(size);
+
+	if (mcpup->cpu_q_va == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: cpu intrq allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
 	mcpup->cpu_q_base_pa = va_to_pa(mcpup->cpu_q_va);
-	mcpup->cpu_q_size =  cpu_q_size;
+	mcpup->cpu_q_size = size;
 
-	dev_q_size = dev_q_entries * INTR_REPORT_SIZE;
-	mcpup->dev_q_va = contig_mem_alloc(dev_q_size);
-	if (mcpup->dev_q_va == NULL)
-		cmn_err(CE_PANIC, "cpu%d: dev intrq allocation failed",
-		    cpu->cpu_id);
+	/*
+	 * Allocate device queues
+	 */
+	size = dev_q_entries * INTR_REPORT_SIZE;
+
+	mcpup->dev_q_va = contig_mem_alloc(size);
+
+	if (mcpup->dev_q_va == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: dev intrq allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
 	mcpup->dev_q_base_pa = va_to_pa(mcpup->dev_q_va);
-	mcpup->dev_q_size =  dev_q_size;
+	mcpup->dev_q_size = size;
 
-	/* Allocate resumable queue and its kernel buffer */
-	cpu_rq_size = cpu_rq_entries * Q_ENTRY_SIZE;
-	mcpup->cpu_rq_va = contig_mem_alloc(2 * cpu_rq_size);
-	if (mcpup->cpu_rq_va == NULL)
-		cmn_err(CE_PANIC, "cpu%d: resumable queue allocation failed",
-		    cpu->cpu_id);
+	/*
+	 * Allocate resumable queue and its kernel buffer
+	 */
+	size = cpu_rq_entries * Q_ENTRY_SIZE;
+
+	mcpup->cpu_rq_va = contig_mem_alloc(2 * size);
+
+	if (mcpup->cpu_rq_va == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: resumable queue allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
 	mcpup->cpu_rq_base_pa = va_to_pa(mcpup->cpu_rq_va);
-	mcpup->cpu_rq_size = cpu_rq_size;
+	mcpup->cpu_rq_size = size;
 	/* zero out the memory */
-	bzero(mcpup->cpu_rq_va, 2 * cpu_rq_size);
+	bzero(mcpup->cpu_rq_va, 2 * size);
 
-	/* Allocate nonresumable queue here */
-	cpu_nrq_size = cpu_nrq_entries * Q_ENTRY_SIZE;
-	mcpup->cpu_nrq_va = contig_mem_alloc(2 * cpu_nrq_size);
-	if (mcpup->cpu_nrq_va == NULL)
-		cmn_err(CE_PANIC, "cpu%d: nonresumable queue "
-		    "allocation failed", cpu->cpu_id);
+	/*
+	 * Allocate non-resumable queues
+	 */
+	size = cpu_nrq_entries * Q_ENTRY_SIZE;
+
+	mcpup->cpu_nrq_va = contig_mem_alloc(2 * size);
+
+	if (mcpup->cpu_nrq_va == NULL) {
+		cmn_err(CE_NOTE, "cpu%d: nonresumable queue allocation failed",
+			cpu->cpu_id);
+		return (ENOMEM);
+	}
 	mcpup->cpu_nrq_base_pa = va_to_pa(mcpup->cpu_nrq_va);
-	mcpup->cpu_nrq_size = cpu_nrq_size;
+	mcpup->cpu_nrq_size = size;
 	/* zero out the memory */
-	bzero(mcpup->cpu_nrq_va, 2 * cpu_nrq_size);
+	bzero(mcpup->cpu_nrq_va, 2 * size);
+
+	return (0);
 }
 
 void
--- a/usr/src/uts/sun4v/os/mach_mp_startup.c	Mon Apr 16 19:43:30 2007 -0700
+++ b/usr/src/uts/sun4v/os/mach_mp_startup.c	Mon Apr 16 22:09:13 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -166,7 +166,8 @@
 mp_cpu_configure(int cpuid)
 {
 	extern void fill_cpu(md_t *, mde_cookie_t);
-	extern void setup_cpu_common(int);
+	extern int setup_cpu_common(int);
+	extern int cleanup_cpu_common(int);
 	extern void setup_exec_unit_mappings(md_t *);
 	md_t *mdp;
 	mde_cookie_t rootnode, cpunode = MDE_INVAL_ELEM_COOKIE;
@@ -226,8 +227,10 @@
 
 	(void) md_fini_handle(mdp);
 
-	setup_cpu_common(cpuid);
-
+	if ((i = setup_cpu_common(cpuid)) != 0) {
+		(void) cleanup_cpu_common(cpuid);
+		return (i);
+	}
 	return (0);
 }