summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-08-17 12:57:01 +0000
committerJohn Levon <john.levon@joyent.com>2019-09-04 02:22:58 -0700
commita8ea0c9dd566453d9b69eab5f863930da9d0c4ae (patch)
tree877187685b58e8cecf3397e20447193296d1ad0a
parentcd4bec9bcc617ecbc586bb4c2feb7096df189b13 (diff)
downloadillumos-joyent-a8ea0c9dd566453d9b69eab5f863930da9d0c4ae.tar.gz
11584 ::xcall would be useful
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.c28
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.h3
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile4
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/unix.c12
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/xcall.c237
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile4
-rw-r--r--usr/src/uts/i86pc/os/x_call.c70
-rw-r--r--usr/src/uts/i86pc/sys/machcpuvar.h3
-rw-r--r--usr/src/uts/i86pc/sys/x_call.h14
9 files changed, 314 insertions, 61 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
index 9af52917b4..1be7357f05 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright (c) 2013, 2016 by Delphix. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#include <mdb/mdb_ctf.h>
@@ -1236,8 +1236,9 @@ member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
"member %s of type %s", name, mp->m_tgtname);
if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
- mdb_ctf_warn(mp->m_flags,
- "could not find %s\n", tgtname);
+ if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
+ return (0);
+ mdb_ctf_warn(mp->m_flags, "could not find %s\n", tgtname);
return (set_errno(EMDB_CTFNOMEMB));
}
@@ -1612,12 +1613,11 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
* Warning: it will therefore only work with enums are only used to store
* legitimate enum values (not several values or-ed together).
*
- * By default, if mdb_ctf_vread() can not find any members or enum values,
- * it will print a descriptive message (with mdb_warn()) and fail.
- * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
- * Additional flags can be used to ignore specific types of translation
- * failure, but should be used with caution, because they will silently leave
- * the caller's buffer uninitialized.
+ * Flags values:
+ *
+ * MDB_CTF_VREAD_QUIET: keep quiet about failures
+ * MDB_CTF_VREAD_IGNORE_ABSENT: ignore any member that couldn't be found in the
+ * target struct; be careful not to use an uninitialized result.
*/
int
mdb_ctf_vread(void *modbuf, const char *target_typename,
@@ -1630,6 +1630,7 @@ mdb_ctf_vread(void *modbuf, const char *target_typename,
mdb_ctf_id_t tgtid;
mdb_ctf_id_t modid;
mdb_module_t *mod;
+ int ret;
if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
@@ -1662,15 +1663,20 @@ mdb_ctf_vread(void *modbuf, const char *target_typename,
return (-1); /* errno is set for us */
}
- tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
+ tgtbuf = mdb_alloc(size, UM_SLEEP);
if (mdb_vread(tgtbuf, size, addr) < 0) {
mdb_ctf_warn(flags, "couldn't read %s from %p\n",
target_typename, addr);
+ mdb_free(tgtbuf, size);
return (-1); /* errno is set for us */
}
- return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
+ ret = vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags);
+
+ mdb_free(tgtbuf, size);
+
+ return (ret);
}
/*
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
index 21f27d782b..74bc8e95da 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
@@ -24,7 +24,7 @@
*/
/*
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _MDB_CTF_H
@@ -142,6 +142,7 @@ extern ssize_t mdb_ctf_offset_to_name(mdb_ctf_id_t, ulong_t, char *, size_t,
int, mdb_ctf_id_t *, ulong_t *);
#define MDB_CTF_VREAD_QUIET 0x100
+#define MDB_CTF_VREAD_IGNORE_ABSENT 0x200
extern int mdb_ctf_vread(void *, const char *, const char *,
uintptr_t, uint_t);
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile
index 23984a8f08..efcfad5375 100644
--- a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile
@@ -22,12 +22,12 @@
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
MODULE = unix.so
MDBTGT = kvm
-MODSRCS = unix.c i86mmu.c
+MODSRCS = unix.c i86mmu.c xcall.c
MODASMSRCS = unix_sup.s
include ../../../../../Makefile.cmd
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
index 24267e6190..e91321b235 100644
--- a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
@@ -802,7 +802,7 @@ scalehrtime_help(void)
/*ARGSUSED*/
static int
-scalehrtime_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+scalehrtime_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
uint32_t nsec_scale;
hrtime_t tsc = addr, hrt, tsc_last, base, mult = 1;
@@ -904,7 +904,7 @@ scalehrtime_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
*/
/*ARGSUSED*/
static int
-x86_featureset_cmd(uintptr_t addr, uint_t flags, int argc,
+x86_featureset_dcmd(uintptr_t addr, uint_t flags, int argc,
const mdb_arg_t *argv)
{
void *fset;
@@ -1035,6 +1035,9 @@ sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
#endif
+extern void xcall_help(void);
+extern int xcall_dcmd(uintptr_t, uint_t, int, const mdb_arg_t *);
+
static const mdb_dcmd_t dcmds[] = {
{ "gate_desc", ":", "dump a gate descriptor", gate_desc },
{ "idt", ":[-v]", "dump an IDT", idt },
@@ -1058,9 +1061,10 @@ static const mdb_dcmd_t dcmds[] = {
mfntopfn_dcmd },
{ "memseg_list", ":", "show memseg list", memseg_list },
{ "scalehrtime", ":[-a|-r]", "scale an unscaled high-res time",
- scalehrtime_cmd, scalehrtime_help },
+ scalehrtime_dcmd, scalehrtime_help },
{ "x86_featureset", NULL, "dump the x86_featureset vector",
- x86_featureset_cmd },
+ x86_featureset_dcmd },
+ { "xcall", ":", "print CPU cross-call state", xcall_dcmd, xcall_help },
#ifdef _KMDB
{ "sysregs", NULL, "dump system registers", sysregs_dcmd },
#endif
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/xcall.c b/usr/src/cmd/mdb/i86pc/modules/unix/xcall.c
new file mode 100644
index 0000000000..a3057daff1
--- /dev/null
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/xcall.c
@@ -0,0 +1,237 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+/*
+ * Copyright 2019 Joyent, Inc.
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ctf.h>
+#include <sys/cpuvar.h>
+#include <sys/x_call.h>
+
+typedef struct {
+ uint32_t xc_work_cnt;
+ struct xc_msg *xc_curmsg;
+ struct xc_msg *xc_msgbox;
+ xc_data_t xc_data;
+} mdb_xcall_machcpu_t;
+
+typedef struct {
+ processorid_t cpu_id;
+ mdb_xcall_machcpu_t cpu_m;
+} mdb_xcall_cpu_t;
+
+typedef struct {
+ uint_t xd_flags;
+ processorid_t xd_cpu_id;
+ size_t xd_msg_index;
+ struct xc_msg xd_msgs[NCPU];
+} xcall_data_t;
+
+void
+xcall_help(void)
+{
+ mdb_printf(
+ "Print all active cross-calls where the given CPU is the master.\n"
+ "The PEND column is ->xc_work_cnt, the pending message count -\n"
+ "this includes both master and slave messages. For each\n"
+ "cross call, the message type and the slave CPU ID are shown.\n");
+}
+
+static int
+cpu_id_to_addr(processorid_t cpun, uintptr_t *addrp)
+{
+ uintptr_t addr;
+ GElf_Sym sym;
+
+ if (mdb_lookup_by_name("cpu", &sym) == -1) {
+ mdb_warn("failed to find symbol for 'cpu'");
+ return (-1);
+ }
+
+ if (cpun * sizeof (uintptr_t) > sym.st_size)
+ return (-1);
+
+ addr = (uintptr_t)sym.st_value + cpun * sizeof (uintptr_t);
+
+ if (mdb_vread(&addr, sizeof (addr), addr) == -1) {
+ mdb_warn("failed to read cpu[%lu]", cpun);
+ return (-1);
+ }
+
+ if (addr != (uintptr_t)NULL) {
+ *addrp = addr;
+ return (0);
+ }
+
+ return (-1);
+}
+
+static int
+xcall_copy_msg(struct xc_msg *msg, xcall_data_t *data, boolean_t current)
+{
+ if (data->xd_msg_index >= NCPU) {
+ mdb_warn("ran out of msg space: %lu >= %lu\n",
+ data->xd_msg_index, NCPU);
+ return (-1);
+ }
+
+ bcopy(msg, &data->xd_msgs[data->xd_msg_index], sizeof (*msg));
+
+ /*
+ * As we don't use .xc_next, store 'current' there.
+ */
+ data->xd_msgs[data->xd_msg_index].xc_next = (void *)(uintptr_t)current;
+ data->xd_msg_index++;
+ return (0);
+}
+
+static int
+xcall_get_msgs(uintptr_t addr, const void *wdata, void *priv)
+{
+ _NOTE(ARGUNUSED(wdata));
+ xcall_data_t *data = priv;
+ mdb_xcall_cpu_t xcpu = { 0, };
+ struct xc_msg msg;
+ uintptr_t msgaddr;
+
+ if (mdb_ctf_vread(&xcpu, "unix`cpu_t", "mdb_xcall_cpu_t",
+ addr, MDB_CTF_VREAD_IGNORE_ABSENT) == -1)
+ return (WALK_ERR);
+
+ if (xcpu.cpu_m.xc_curmsg != NULL) {
+ msgaddr = (uintptr_t)xcpu.cpu_m.xc_curmsg;
+
+ if (mdb_vread(&msg, sizeof (msg), msgaddr) != sizeof (msg))
+ return (WALK_ERR);
+
+ if (msg.xc_master == data->xd_cpu_id) {
+ if (data->xd_flags & DCMD_PIPE_OUT)
+ mdb_printf("%p\n", msgaddr);
+ else if (xcall_copy_msg(&msg, data, B_TRUE) != 0)
+ return (WALK_ERR);
+ }
+ }
+
+ for (msgaddr = (uintptr_t)xcpu.cpu_m.xc_msgbox;
+ msgaddr != (uintptr_t)NULL; msgaddr = (uintptr_t)msg.xc_next) {
+ if (mdb_vread(&msg, sizeof (msg), msgaddr) != sizeof (msg))
+ return (WALK_ERR);
+
+ if (msg.xc_master != data->xd_cpu_id)
+ continue;
+
+ if (data->xd_flags & DCMD_PIPE_OUT)
+ mdb_printf("%p\n", msgaddr);
+ else if (xcall_copy_msg(&msg, data, B_FALSE) != 0)
+ return (WALK_ERR);
+ }
+
+ return (WALK_NEXT);
+}
+
+static int
+print_xcall_msg(struct xc_msg *msg)
+{
+ boolean_t current = (boolean_t)msg->xc_next;
+ char indent[] = " ";
+ const char *cmd;
+
+ switch (msg->xc_command) {
+ case XC_MSG_ASYNC: cmd = "ASYNC"; break;
+ case XC_MSG_CALL: cmd = "CALL"; break;
+ case XC_MSG_SYNC: cmd = "SYNC"; break;
+ case XC_MSG_FREE:cmd = "FREE"; break;
+ case XC_MSG_WAITING: cmd = "WAITING"; break;
+ case XC_MSG_RELEASED: cmd = "RELEASED"; break;
+ case XC_MSG_DONE: cmd = "DONE"; break;
+ default: cmd = "?"; break;
+ }
+
+ mdb_printf("%s %s%-*s %-6u\n", indent, current ? "*" : "",
+ 9 - current, cmd, msg->xc_slave);
+ return (0);
+}
+
+/*
+ * Show all xcall messages where the master is the given CPU.
+ *
+ * As non-free messages can be on the slave's ->xc_msgbox or ->xc_curmsg, we
+ * need to walk across all of them to find each message where ->xc_master
+ * is our CPU ID.
+ */
+int
+xcall_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ mdb_xcall_cpu_t xcpu = { 0, };
+ xcall_data_t data = { 0, };
+
+ if (mdb_getopts(argc, argv, NULL) != argc)
+ return (DCMD_USAGE);
+
+ /*
+ * Yep, this will re-collect all the messages each time. Shrug.
+ */
+ if (!(flags & DCMD_ADDRSPEC)) {
+ if (mdb_pwalk_dcmd("cpu", "xcall", argc, argv, 0) == -1) {
+ mdb_warn("can't walk CPUs");
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+ }
+
+ if (addr < NCPU && cpu_id_to_addr((processorid_t)addr, &addr) != 0) {
+ mdb_warn("invalid CPU ID %lu\n", addr);
+ return (DCMD_ERR);
+ }
+
+ if (mdb_ctf_vread(&xcpu, "unix`cpu_t", "mdb_xcall_cpu_t",
+ addr, MDB_CTF_VREAD_IGNORE_ABSENT) == -1) {
+ mdb_warn("couldn't read cpu 0x%lx", addr);
+ return (DCMD_ERR);
+ }
+
+ data.xd_cpu_id = xcpu.cpu_id;
+ data.xd_flags = flags;
+
+ if (mdb_pwalk("cpu", xcall_get_msgs, &data, (uintptr_t)NULL) == -1) {
+ mdb_warn("can't walk CPUs");
+ return (DCMD_ERR);
+ }
+
+ if (flags & DCMD_PIPE_OUT)
+ return (DCMD_OK);
+
+ if (DCMD_HDRSPEC(flags))
+ mdb_printf("%<u>%3s %4s %s%</u>\n", "CPU", "PEND", "HANDLER");
+
+ if (data.xd_msg_index == 0) {
+ mdb_printf("%3d %4d -\n",
+ xcpu.cpu_id, xcpu.cpu_m.xc_work_cnt);
+ return (DCMD_OK);
+ }
+
+ mdb_printf("%3d %4d %a(%a, %a, %a)\n",
+ xcpu.cpu_id, xcpu.cpu_m.xc_work_cnt,
+ xcpu.cpu_m.xc_data.xc_func, xcpu.cpu_m.xc_data.xc_a1,
+ xcpu.cpu_m.xc_data.xc_a2, xcpu.cpu_m.xc_data.xc_a3);
+
+ if (!(flags & DCMD_PIPE_OUT))
+ mdb_printf(" %<u>%-9s %-6s%</u>\n", "COMMAND", "SLAVE");
+
+ for (size_t i = 0; i < data.xd_msg_index; i++) {
+ if (print_xcall_msg(&data.xd_msgs[i]) != 0)
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+}
diff --git a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile
index 190631bbf0..32c1fe33fd 100644
--- a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile
+++ b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile
@@ -22,12 +22,12 @@
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
MODULE = unix.so
MDBTGT = kvm
-MODSRCS = unix.c i86mmu.c
+MODSRCS = unix.c i86mmu.c xcall.c
MODASMSRCS = unix_sup.s
include ../../../../../Makefile.cmd
diff --git a/usr/src/uts/i86pc/os/x_call.c b/usr/src/uts/i86pc/os/x_call.c
index 814e7a0026..4eeb5aaa08 100644
--- a/usr/src/uts/i86pc/os/x_call.c
+++ b/usr/src/uts/i86pc/os/x_call.c
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/types.h>
@@ -79,38 +80,29 @@
* on a different Virtual Address at the same time. The old code required
* N squared IPIs. With this method, depending on timing, it could happen
* with just N IPIs.
- */
-
-/*
- * The default is to not enable collecting counts of IPI information, since
- * the updating of shared cachelines could cause excess bus traffic.
- */
-uint_t xc_collect_enable = 0;
-uint64_t xc_total_cnt = 0; /* total #IPIs sent for cross calls */
-uint64_t xc_multi_cnt = 0; /* # times we piggy backed on another IPI */
-
-/*
- * Values for message states. Here are the normal transitions. A transition
- * of "->" happens in the slave cpu and "=>" happens in the master cpu as
- * the messages are passed back and forth.
+ *
+ * Here are the normal transitions for XC_MSG_* values in ->xc_command. A
+ * transition of "->" happens in the slave cpu and "=>" happens in the master
+ * cpu as the messages are passed back and forth.
*
* FREE => ASYNC -> DONE => FREE
* FREE => CALL -> DONE => FREE
* FREE => SYNC -> WAITING => RELEASED -> DONE => FREE
*
- * The interesing one above is ASYNC. You might ask, why not go directly
- * to FREE, instead of DONE. If it did that, it might be possible to exhaust
+ * The interesting one above is ASYNC. You might ask, why not go directly
+ * to FREE, instead of DONE? If it did that, it might be possible to exhaust
* the master's xc_free list if a master can generate ASYNC messages faster
* then the slave can process them. That could be handled with more complicated
* handling. However since nothing important uses ASYNC, I've not bothered.
*/
-#define XC_MSG_FREE (0) /* msg in xc_free queue */
-#define XC_MSG_ASYNC (1) /* msg in slave xc_msgbox */
-#define XC_MSG_CALL (2) /* msg in slave xc_msgbox */
-#define XC_MSG_SYNC (3) /* msg in slave xc_msgbox */
-#define XC_MSG_WAITING (4) /* msg in master xc_msgbox or xc_waiters */
-#define XC_MSG_RELEASED (5) /* msg in slave xc_msgbox */
-#define XC_MSG_DONE (6) /* msg in master xc_msgbox */
+
+/*
+ * The default is to not enable collecting counts of IPI information, since
+ * the updating of shared cachelines could cause excess bus traffic.
+ */
+uint_t xc_collect_enable = 0;
+uint64_t xc_total_cnt = 0; /* total #IPIs sent for cross calls */
+uint64_t xc_multi_cnt = 0; /* # times we piggy backed on another IPI */
/*
* We allow for one high priority message at a time to happen in the system.
@@ -121,13 +113,6 @@ static volatile ulong_t *xc_priority_set = CPUSET2BV(xc_priority_set_store);
static xc_data_t xc_priority_data;
/*
- * Wrappers to avoid C compiler warnings due to volatile. The atomic bit
- * operations don't accept volatile bit vectors - which is a bit silly.
- */
-#define XC_BT_SET(vector, b) BT_ATOMIC_SET((ulong_t *)(vector), (b))
-#define XC_BT_CLEAR(vector, b) BT_ATOMIC_CLEAR((ulong_t *)(vector), (b))
-
-/*
* Decrement a CPU's work count
*/
static void
@@ -193,6 +178,20 @@ xc_extract(xc_msg_t **queue)
}
/*
+ * Extract the next message from the CPU's queue, and place the message in
+ * .xc_curmsg. The latter is solely to make debugging (and ::xcall) more
+ * useful.
+ */
+static xc_msg_t *
+xc_get(void)
+{
+ struct machcpu *mcpup = &CPU->cpu_m;
+ xc_msg_t *msg = xc_extract(&mcpup->xc_msgbox);
+ mcpup->xc_curmsg = msg;
+ return (msg);
+}
+
+/*
* Initialize the machcpu fields used for cross calls
*/
static uint_t xc_initialized = 0;
@@ -328,8 +327,7 @@ xc_serv(caddr_t arg1, caddr_t arg2)
/*
* We may have to wait for a message to arrive.
*/
- for (msg = NULL; msg == NULL;
- msg = xc_extract(&mcpup->xc_msgbox)) {
+ for (msg = NULL; msg == NULL; msg = xc_get()) {
/*
* Alway check for and handle a priority message.
@@ -339,7 +337,7 @@ xc_serv(caddr_t arg1, caddr_t arg2)
a1 = xc_priority_data.xc_a1;
a2 = xc_priority_data.xc_a2;
a3 = xc_priority_data.xc_a3;
- XC_BT_CLEAR(xc_priority_set, CPU->cpu_id);
+ BT_ATOMIC_CLEAR(xc_priority_set, CPU->cpu_id);
xc_decrement(mcpup);
func(a1, a2, a3);
if (mcpup->xc_work_cnt == 0)
@@ -443,6 +441,8 @@ xc_serv(caddr_t arg1, caddr_t arg2)
panic("bad message 0x%p in msgbox", (void *)msg);
break;
}
+
+ CPU->cpu_m.xc_curmsg = NULL;
}
return (rc);
}
@@ -581,7 +581,7 @@ xc_priority_common(
* ahead.
*/
if (BT_TEST(xc_priority_set, c)) {
- XC_BT_CLEAR(xc_priority_set, c);
+ BT_ATOMIC_CLEAR(xc_priority_set, c);
if (cpup->cpu_m.xc_work_cnt > 0)
xc_decrement(&cpup->cpu_m);
}
@@ -607,7 +607,7 @@ xc_priority_common(
cpup == CPU)
continue;
(void) xc_increment(&cpup->cpu_m);
- XC_BT_SET(xc_priority_set, c);
+ BT_ATOMIC_SET(xc_priority_set, c);
send_dirint(c, XC_HI_PIL);
for (i = 0; i < 10; ++i) {
(void) atomic_cas_ptr(&cpup->cpu_m.xc_msgbox,
diff --git a/usr/src/uts/i86pc/sys/machcpuvar.h b/usr/src/uts/i86pc/sys/machcpuvar.h
index 3eb5ef76f2..f4e38dec98 100644
--- a/usr/src/uts/i86pc/sys/machcpuvar.h
+++ b/usr/src/uts/i86pc/sys/machcpuvar.h
@@ -152,7 +152,7 @@ typedef struct cpu_smt {
*
* There are CTASSERTs in os/intr.c that verify this all works out.
*/
-#define MACHCPU_SIZE (1568 + 688)
+#define MACHCPU_SIZE (1568 + 696)
#define MACHCPU_PAD (MMU_PAGESIZE - MACHCPU_SIZE)
#define MACHCPU_PAD2 (MMU_PAGESIZE - 16 - 3 * sizeof (struct kpti_frame))
@@ -161,6 +161,7 @@ struct machcpu {
* x_call fields - used for interprocessor cross calls
*/
struct xc_msg *xc_msgbox;
+ struct xc_msg *xc_curmsg;
struct xc_msg *xc_free;
xc_data_t xc_data;
uint32_t xc_wait_cnt;
diff --git a/usr/src/uts/i86pc/sys/x_call.h b/usr/src/uts/i86pc/sys/x_call.h
index 65b5813b95..c1e55495b0 100644
--- a/usr/src/uts/i86pc/sys/x_call.h
+++ b/usr/src/uts/i86pc/sys/x_call.h
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_X_CALL_H
@@ -33,6 +34,14 @@ extern "C" {
#ifndef _ASM
+#define XC_MSG_FREE (0) /* msg in xc_free queue */
+#define XC_MSG_ASYNC (1) /* msg in slave xc_msgbox */
+#define XC_MSG_CALL (2) /* msg in slave xc_msgbox */
+#define XC_MSG_SYNC (3) /* msg in slave xc_msgbox */
+#define XC_MSG_WAITING (4) /* msg in master xc_msgbox or xc_waiters */
+#define XC_MSG_RELEASED (5) /* msg in slave xc_msgbox */
+#define XC_MSG_DONE (6) /* msg in master xc_msgbox */
+
typedef uintptr_t xc_arg_t;
typedef int (*xc_func_t)(xc_arg_t, xc_arg_t, xc_arg_t);
@@ -52,13 +61,8 @@ typedef struct xc_data {
*/
typedef struct xc_msg {
uint8_t xc_command;
-#ifdef __amd64
uint16_t xc_master;
uint16_t xc_slave;
-#else
- uint8_t xc_master;
- uint8_t xc_slave;
-#endif
struct xc_msg *xc_next;
} xc_msg_t;