Mercurial > illumos > illumos-gate
changeset 1310:c5ae4308e0b9
6348868 kernel should handle ECPUERROR return code from shipit()
6363558 optimize sun4v cpu cross call
6366134 sun4v SEND_MONDO_STATS code has unnecessary comparison
6370233 on sun4v platforms dtrace sdt xcalls probe is inaccurate
author | ha137994 |
---|---|
date | Mon, 23 Jan 2006 14:44:17 -0800 |
parents | 7e225a50e07d |
children | 39d57b0b8fba |
files | usr/src/uts/sun4/os/x_call.c usr/src/uts/sun4/sys/xc_impl.h usr/src/uts/sun4v/os/mach_cpu_states.c usr/src/uts/sun4v/sys/hypervisor_api.h |
diffstat | 4 files changed, 153 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/sun4/os/x_call.c Mon Jan 23 13:07:36 2006 -0800 +++ b/usr/src/uts/sun4/os/x_call.c Mon Jan 23 14:44:17 2006 -0800 @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -755,19 +755,8 @@ /* * inform the target processors to enter into xc_loop() */ - tmpset = xc_cpuset; init_mondo(setsoftint_tl1, xc_loop_inum, 0); - for (pix = 0; pix < NCPU; pix++) { - if (CPU_IN_SET(tmpset, pix)) { - ASSERT(xc_mbox[pix].xc_state == XC_IDLE); - xc_mbox[pix].xc_state = XC_ENTER; - send_one_mondo(pix); - CPUSET_DEL(tmpset, pix); - if (CPUSET_ISNULL(tmpset)) { - break; - } - } - } + SEND_MBOX_MONDO_XC_ENTER(xc_cpuset); xc_spl_enter[lcx] = 0; /*
--- a/usr/src/uts/sun4/sys/xc_impl.h Mon Jan 23 13:07:36 2006 -0800 +++ b/usr/src/uts/sun4/sys/xc_impl.h Mon Jan 23 14:44:17 2006 -0800 @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -148,13 +148,35 @@ if (CPU_IN_SET(tmpset, pix)) { \ ASSERT(xc_mbox[pix].xc_state == state); \ XC_SETUP(pix, func, arg1, arg2); \ - membar_stld(); \ - send_one_mondo(pix); \ CPUSET_DEL(tmpset, pix); \ if (CPUSET_ISNULL(tmpset)) \ break; \ } \ } \ + membar_stld(); \ + send_mondo_set(xc_cpuset); \ +} + +/* + * set up and notify a x-call request, signalling xc_cpuset + * cpus to enter xc_loop() + */ +#define SEND_MBOX_MONDO_XC_ENTER(xc_cpuset) \ +{ \ + int pix; \ + cpuset_t tmpset = xc_cpuset; \ + for (pix = 0; pix < NCPU; pix++) { \ + if (CPU_IN_SET(tmpset, pix)) { \ + ASSERT(xc_mbox[pix].xc_state == \ + XC_IDLE); \ + xc_mbox[pix].xc_state = XC_ENTER; \ + CPUSET_DEL(tmpset, pix); \ + if (CPUSET_ISNULL(tmpset)) { \ + break; \ + } \ + } \ + } \ + send_mondo_set(xc_cpuset); \ } /*
--- a/usr/src/uts/sun4v/os/mach_cpu_states.c Mon Jan 23 13:07:36 2006 -0800 +++ b/usr/src/uts/sun4v/os/mach_cpu_states.c Mon Jan 23 14:44:17 2006 -0800 @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -591,8 +591,20 @@ stat = shipit(1, mcpup->cpu_list_ra); endtick = starttick + xc_tick_limit; retries = 0; - while (stat != 0) { - ASSERT(stat == H_EWOULDBLOCK); + while (stat != H_EOK) { + if (stat != H_EWOULDBLOCK) { + if (panic_quiesce) + return; + if (stat == H_ECPUERROR) + cmn_err(CE_PANIC, "send_one_mondo: " + "cpuid: 0x%x has been marked in " + "error", cpuid); + else + cmn_err(CE_PANIC, "send_one_mondo: " + "unexpected hypervisor error 0x%x " + "while sending a mondo to cpuid: " + "0x%x", stat, cpuid); + } tick = gettick(); /* * If there is a big jump between the current tick @@ -615,11 +627,11 @@ } #ifdef SEND_MONDO_STATS { - int n = gettick() - starttick; + uint64_t n = gettick() - starttick; if (n < 8192) x_one_stimes[n >> 7]++; - else if (n < 16*8192) - x_one_ltimes[(n >> 13) & 0xf]++; + else if (n < 15*8192) + x_one_ltimes[n >> 13]++; else x_one_ltimes[0xf]++; } @@ -630,38 +642,110 @@ send_mondo_set(cpuset_t set) { uint64_t starttick, endtick, tick, lasttick; - int i, retries, stat, fcpuid, lcpuid; - int ncpuids = 0; int shipped = 0; + int retries = 0; struct machcpu *mcpup = &(CPU->cpu_m); ASSERT(!CPUSET_ISNULL(set)); starttick = lasttick = gettick(); endtick = starttick + xc_tick_limit; - fcpuid = -1; - for (i = 0; i < NCPU; i++) { - if (CPU_IN_SET(set, i)) { - ncpuids++; - mcpup->cpu_list[0] = (uint16_t)i; - stat = shipit(1, mcpup->cpu_list_ra); - if (stat != 0) { - ASSERT(stat == H_EWOULDBLOCK); - if (fcpuid < 0) - fcpuid = i; - lcpuid = i; - continue; + do { + int ncpuids = 0; + int i, stat; + + /* assemble CPU list for HV argument */ + for (i = 0; i < NCPU; i++) { + if (CPU_IN_SET(set, i)) { + mcpup->cpu_list[ncpuids] = (uint16_t)i; + ncpuids++; + } + } + + stat = shipit(ncpuids, mcpup->cpu_list_ra); + if (stat == H_EOK) { + shipped += ncpuids; + break; + } + + /* + * Either not all CPU mondos were sent, or an + * error occurred. CPUs that were sent mondos + * have their CPU IDs overwritten in cpu_list. + * Reset the cpuset so that its only members + * are those CPU IDs that still need to be sent. + */ + CPUSET_ZERO(set); + for (i = 0; i < ncpuids; i++) { + if (mcpup->cpu_list[i] == HV_SEND_MONDO_ENTRYDONE) { + shipped++; + } else { + CPUSET_ADD(set, mcpup->cpu_list[i]); } - shipped++; - CPUSET_DEL(set, i); - if (CPUSET_ISNULL(set)) - break; } - } + + /* + * Now handle possible errors returned + * from hypervisor. + */ + if (stat == H_ECPUERROR) { + cpuset_t error_set; + + /* + * One or more of the CPUs passed to HV is + * in the error state. Remove those CPUs from + * set and record them in error_set. + */ + CPUSET_ZERO(error_set); + for (i = 0; i < NCPU; i++) { + if (CPU_IN_SET(set, i)) { + uint64_t state; + (void) hv_cpu_state(i, &state); + if (state == CPU_STATE_ERROR) { + CPUSET_ADD(error_set, i); + CPUSET_DEL(set, i); + } + } + } - retries = 0; - while (shipped < ncpuids) { - ASSERT(fcpuid >= 0 && fcpuid <= lcpuid && lcpuid < NCPU); + if (!panic_quiesce) { + if (CPUSET_ISNULL(error_set)) { + cmn_err(CE_PANIC, "send_mondo_set: " + "hypervisor returned " + "H_ECPUERROR but no CPU in " + "cpu_list in error state"); + } + + cmn_err(CE_CONT, "send_mondo_set: cpuid(s) "); + for (i = 0; i < NCPU; i++) { + if (CPU_IN_SET(error_set, i)) { + cmn_err(CE_CONT, "0x%x ", i); + } + } + cmn_err(CE_CONT, "have been marked in " + "error\n"); + cmn_err(CE_PANIC, "send_mondo_set: CPU(s) " + "in error state"); + } + } else if (stat != H_EWOULDBLOCK) { + if (panic_quiesce) + return; + /* + * For all other errors, panic. + */ + cmn_err(CE_CONT, "send_mondo_set: unexpected " + "hypervisor error 0x%x while sending a " + "mondo to cpuid(s):", stat); + for (i = 0; i < NCPU; i++) { + if (CPU_IN_SET(set, i)) { + cmn_err(CE_CONT, " 0x%x", i); + } + } + cmn_err(CE_CONT, "\n"); + cmn_err(CE_PANIC, "send_mondo_set: unexpected " + "hypervisor error"); + } + tick = gettick(); /* * If there is a big jump between the current tick @@ -676,54 +760,27 @@ return; cmn_err(CE_CONT, "send mondo timeout " "[retries: 0x%x] cpuids: ", retries); - for (i = fcpuid; i <= lcpuid; i++) { + for (i = 0; i < NCPU; i++) if (CPU_IN_SET(set, i)) cmn_err(CE_CONT, " 0x%x", i); - } cmn_err(CE_CONT, "\n"); cmn_err(CE_PANIC, "send_mondo_set: timeout"); } - /* adjust fcpuid to the first CPU in set */ - for (; fcpuid <= lcpuid; fcpuid++) - if (CPU_IN_SET(set, fcpuid)) - break; - - /* adjust lcpuid to the last CPU in set */ - for (; lcpuid >= fcpuid; lcpuid--) - if (CPU_IN_SET(set, lcpuid)) - break; - - /* resend undelivered mondo */ - for (i = fcpuid; i <= lcpuid; i++) { - if (CPU_IN_SET(set, i)) { - mcpup->cpu_list[0] = (uint16_t)i; - stat = shipit(1, mcpup->cpu_list_ra); - if (stat != 0) { - ASSERT(stat == H_EWOULDBLOCK); - continue; - } - shipped++; - CPUSET_DEL(set, i); - if (shipped == ncpuids) - break; - } - } - if (shipped == ncpuids) - break; - while (gettick() < (tick + sys_clock_mhz)) ; retries++; - } + } while (!CPUSET_ISNULL(set)); + + CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); #ifdef SEND_MONDO_STATS { - int n = gettick() - starttick; + uint64_t n = gettick() - starttick; if (n < 8192) x_set_stimes[n >> 7]++; - else if (n < 16*8192) - x_set_ltimes[(n >> 13) & 0xf]++; + else if (n < 15*8192) + x_set_ltimes[n >> 13]++; else x_set_ltimes[0xf]++; }
--- a/usr/src/uts/sun4v/sys/hypervisor_api.h Mon Jan 23 13:07:36 2006 -0800 +++ b/usr/src/uts/sun4v/sys/hypervisor_api.h Mon Jan 23 14:44:17 2006 -0800 @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,6 +73,12 @@ #define H_BREAK -1 /* Console Break */ #define H_HUP -2 /* Console Break */ + +/* + * Mondo CPU ID argument processing. + */ +#define HV_SEND_MONDO_ENTRYDONE 0xffff + /* * Function numbers for FAST_TRAP. */