summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjb145095 <none@none>2007-04-16 22:09:13 -0700
committerjb145095 <none@none>2007-04-16 22:09:13 -0700
commit982b91072930da051b05465dbd43c5ff024c96bc (patch)
treef3507859e6f847df9556881455e4059f294fc25e
parent789e0dbbcdddab55f064dbca13950cb068a30efe (diff)
downloadillumos-gate-onnv_63.tar.gz
6479998 CPU DR should not panic the system on memory allocation failureonnv_63
-rw-r--r--usr/src/uts/sun4/os/mp_startup.c28
-rw-r--r--usr/src/uts/sun4/os/startup.c7
-rw-r--r--usr/src/uts/sun4u/os/mach_mp_startup.c15
-rw-r--r--usr/src/uts/sun4u/os/mach_startup.c5
-rw-r--r--usr/src/uts/sun4v/os/intrq.c139
-rw-r--r--usr/src/uts/sun4v/os/mach_mp_startup.c11
6 files changed, 126 insertions, 79 deletions
diff --git a/usr/src/uts/sun4/os/mp_startup.c b/usr/src/uts/sun4/os/mp_startup.c
index cb793f3563..8436db7273 100644
--- a/usr/src/uts/sun4/os/mp_startup.c
+++ b/usr/src/uts/sun4/os/mp_startup.c
@@ -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 @@ int trap_trace_inuse[NCPU];
/*
* 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 @@ setup_cpu_common(int cpuid)
#endif /* TRAPTRACE */
extern void idle();
+ int rval;
ASSERT(MUTEX_HELD(&cpu_lock));
ASSERT(cpu[cpuid] == NULL);
@@ -419,13 +420,16 @@ setup_cpu_common(int cpuid)
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 @@ cleanup_cpu_common(int cpuid)
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 @@ cleanup_cpu_common(int cpuid)
*/
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 @@ slave_startup(void)
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 @@ start_other_cpus(int flag)
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);
diff --git a/usr/src/uts/sun4/os/startup.c b/usr/src/uts/sun4/os/startup.c
index ffa5783f4a..36c62b2343 100644
--- a/usr/src/uts/sun4/os/startup.c
+++ b/usr/src/uts/sun4/os/startup.c
@@ -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 @@ startup_end(void)
*/
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);
diff --git a/usr/src/uts/sun4u/os/mach_mp_startup.c b/usr/src/uts/sun4u/os/mach_mp_startup.c
index ad0b76e1c6..243e56a3ac 100644
--- a/usr/src/uts/sun4u/os/mach_mp_startup.c
+++ b/usr/src/uts/sun4u/os/mach_mp_startup.c
@@ -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 @@ int
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 @@ mp_cpu_configure(int cpuid)
*/
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);
}
diff --git a/usr/src/uts/sun4u/os/mach_startup.c b/usr/src/uts/sun4u/os/mach_startup.c
index daa681b744..d2605b75c5 100644
--- a/usr/src/uts/sun4u/os/mach_startup.c
+++ b/usr/src/uts/sun4u/os/mach_startup.c
@@ -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 @@ mach_cpu_halt_idle()
}
/*ARGSUSED*/
-void
+int
cpu_intrq_setup(struct cpu *cp)
{
/* Interrupt mondo queues not applicable to sun4u */
+ return (0);
}
/*ARGSUSED*/
diff --git a/usr/src/uts/sun4v/os/intrq.c b/usr/src/uts/sun4v/os/intrq.c
index ae905ed312..e2158a703b 100644
--- a/usr/src/uts/sun4v/os/intrq.c
+++ b/usr/src/uts/sun4v/os/intrq.c
@@ -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 @@ cpu_intrq_register(struct cpu *cpu)
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;
/*
- * Allocate mondo data for xcalls.
+ * 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.
*/
- 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
+ * Allocate mondo data 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);
+ mcpup->mondo_data = contig_mem_alloc(INTR_REPORT_SIZE);
+ 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 @@ cpu_intrq_setup(struct cpu *cpu)
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;
+
+ /*
+ * Allocate device queues
+ */
+ size = dev_q_entries * INTR_REPORT_SIZE;
+
+ mcpup->dev_q_va = contig_mem_alloc(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);
+ 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;
-
- /* 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);
+ mcpup->dev_q_size = size;
+
+ /*
+ * 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);
-
- /* 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);
+ bzero(mcpup->cpu_rq_va, 2 * size);
+
+ /*
+ * 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
diff --git a/usr/src/uts/sun4v/os/mach_mp_startup.c b/usr/src/uts/sun4v/os/mach_mp_startup.c
index 7d4df1fe7d..4c9ee0d057 100644
--- a/usr/src/uts/sun4v/os/mach_mp_startup.c
+++ b/usr/src/uts/sun4v/os/mach_mp_startup.c
@@ -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 @@ int
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 @@ mp_cpu_configure(int cpuid)
(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);
}