summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-08-10 16:05:23 +0100
committerDan McDonald <danmcd@joyent.com>2018-08-13 14:44:43 -0400
commit309b04b88ca20521fb8141c40ad19b8528b37d7d (patch)
treef9ae6e1f69fb3c23920bb0a769ffb86c59868054 /usr/src
parent734b3a42d9fd315e40f7ce511604865fb3c2e799 (diff)
downloadillumos-gate-309b04b88ca20521fb8141c40ad19b8528b37d7d.tar.gz
9723 provide support for VMM's GDT handling
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Yuri Pankov <yuripv@yuripv.net> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/unix.c12
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h2
-rw-r--r--usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s47
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf1
-rw-r--r--usr/src/test/os-tests/runfiles/default.run2
-rw-r--r--usr/src/test/os-tests/tests/i386/Makefile15
-rw-r--r--usr/src/test/os-tests/tests/i386/badseg.c146
-rw-r--r--usr/src/uts/intel/ia32/os/desctbls.c22
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h4
9 files changed, 201 insertions, 50 deletions
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
index 2d37b73243..92ac3f83ca 100644
--- a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c
@@ -904,9 +904,11 @@ x86_featureset_cmd(uintptr_t addr, uint_t flags, int argc,
#ifdef _KMDB
/* ARGSUSED */
static int
-crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
ulong_t cr0, cr2, cr3, cr4;
+ desctbr_t gdtr;
+
static const mdb_bitmask_t cr0_flag_bits[] = {
{ "PE", CR0_PE, CR0_PE },
{ "MP", CR0_MP, CR0_MP },
@@ -953,6 +955,9 @@ crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
cr2 = kmdb_unix_getcr2();
cr3 = kmdb_unix_getcr3();
cr4 = kmdb_unix_getcr4();
+
+ kmdb_unix_getgdtr(&gdtr);
+
mdb_printf("%%cr0 = 0x%lx <%b>\n", cr0, cr0, cr0_flag_bits);
mdb_printf("%%cr2 = 0x%lx <%a>\n", cr2, cr2);
@@ -966,6 +971,9 @@ crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf("%%cr4 = 0x%lx <%b>\n", cr4, cr4, cr4_flag_bits);
+ mdb_printf("%%gdtr.base = 0x%lx, %%gdtr.limit = 0x%hx\n",
+ gdtr.dtr_base, gdtr.dtr_limit);
+
return (DCMD_OK);
}
#endif
@@ -997,7 +1005,7 @@ static const mdb_dcmd_t dcmds[] = {
{ "x86_featureset", NULL, "dump the x86_featureset vector",
x86_featureset_cmd },
#ifdef _KMDB
- { "crregs", NULL, "dump control registers", crregs_dcmd },
+ { "sysregs", NULL, "dump system registers", sysregs_dcmd },
#endif
{ NULL }
};
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h b/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h
index 4c155373ea..0c9d2e68ec 100644
--- a/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h
@@ -21,6 +21,7 @@
*/
#include <sys/types.h>
+#include <sys/segments.h>
#ifdef __cplusplus
extern "C" {
@@ -30,6 +31,7 @@ extern ulong_t kmdb_unix_getcr0(void);
extern ulong_t kmdb_unix_getcr2(void);
extern ulong_t kmdb_unix_getcr3(void);
extern ulong_t kmdb_unix_getcr4(void);
+extern void kmdb_unix_getgdtr(desctbr_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s b/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s
index 38ddf5cf44..5984a12132 100644
--- a/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s
+++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s
@@ -13,35 +13,20 @@
* Copyright 2018 Joyent, Inc.
*/
-#if !defined(__lint)
- .file "unix_sup.s"
-#endif /* __lint */
-
/*
* Support routines for the unix kmdb module
*/
-#include <sys/asm_linkage.h>
-
#if defined(__lint)
#include <sys/types.h>
-ulong_t
-kmdb_unix_getcr0(void)
-{ return (0); }
-
-ulong_t
-kmdb_unix_getcr3(void)
-{ return (0); }
+#else
-ulong_t
-kmdb_unix_getcr4(void)
-{ return (0); }
+#include <sys/asm_linkage.h>
-#else /* __lint */
+ .file "unix_sup.s"
-#if defined(__amd64)
ENTRY(kmdb_unix_getcr0)
movq %cr0, %rax
ret
@@ -62,27 +47,9 @@ kmdb_unix_getcr4(void)
ret
SET_SIZE(kmdb_unix_getcr4)
-#elif defined (__i386)
- ENTRY(kmdb_unix_getcr0)
- movl %cr0, %eax
- ret
- SET_SIZE(kmdb_unix_getcr0)
-
- ENTRY(kmdb_unix_getcr2)
- movl %cr2, %eax
- ret
- SET_SIZE(kmdb_unix_getcr2)
-
- ENTRY(kmdb_unix_getcr3)
- movl %cr3, %eax
+ ENTRY(kmdb_unix_getgdtr)
+ sgdt (%rdi)
ret
- SET_SIZE(kmdb_unix_getcr3)
-
- ENTRY(kmdb_unix_getcr4)
- movl %cr4, %eax
- ret
- SET_SIZE(kmdb_unix_getcr4)
-
-#endif /* __i386 */
+ SET_SIZE(kmdb_unix_getgdtr)
-#endif /* __lint */
+#endif /* !__lint */
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index 1b7705e816..935920cc83 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -41,6 +41,7 @@ file path=opt/os-tests/tests/file-locking/acquire-lock.32 mode=0555
file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555
file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555
file path=opt/os-tests/tests/file-locking/runtests.64 mode=0555
+$(i386_ONLY)file path=opt/os-tests/tests/i386/badseg mode=0555
$(i386_ONLY)file path=opt/os-tests/tests/i386/ldt mode=0555
file path=opt/os-tests/tests/pf_key/acquire-compare mode=0555
file path=opt/os-tests/tests/pf_key/acquire-spray mode=0555
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index 8279f588e3..d67642f32b 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -66,4 +66,4 @@ tests = ['acquire-compare', 'acquire-spray']
[/opt/os-tests/tests/i386]
user = root
arch = i86pc
-tests = ['ldt']
+tests = ['ldt', 'badseg']
diff --git a/usr/src/test/os-tests/tests/i386/Makefile b/usr/src/test/os-tests/tests/i386/Makefile
index 6c1f480b88..4933cf6e02 100644
--- a/usr/src/test/os-tests/tests/i386/Makefile
+++ b/usr/src/test/os-tests/tests/i386/Makefile
@@ -16,28 +16,29 @@
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
-PROG += ldt
+PROGS += ldt badseg
ROOTOPTPKG = $(ROOT)/opt/os-tests
TESTDIR = $(ROOTOPTPKG)/tests/i386
+ROOTOPTPROGS = $(PROGS:%=$(TESTDIR)/%)
CSTD = $(CSTD_GNU99)
-CMDS = $(PROG:%=$(TESTDIR)/%)
-$(CMDS) := FILEMODE = 0555
+# for badseg
+COPTFLAG =
-all: $(PROG)
+all: $(PROGS)
-install: all $(CMDS)
+install: all $(ROOTOPTPROGS)
lint:
clobber: clean
- -$(RM) $(PROG)
+ -$(RM) $(PROGS)
clean:
-$(CMDS): $(TESTDIR) $(PROG)
+$(ROOTOPTPROGS): $(TESTDIR) $(PROGS)
$(TESTDIR):
$(INS.dir)
diff --git a/usr/src/test/os-tests/tests/i386/badseg.c b/usr/src/test/os-tests/tests/i386/badseg.c
new file mode 100644
index 0000000000..6bf4e0260f
--- /dev/null
+++ b/usr/src/test/os-tests/tests/i386/badseg.c
@@ -0,0 +1,146 @@
+/*
+ * 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 2018 Joyent, Inc.
+ */
+
+#include <stdlib.h>
+#include <ucontext.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/regset.h>
+
+/*
+ * Load a bunch of bad selectors into the seg regs: this will typically cause
+ * the child process to core dump, but it shouldn't panic the kernel...
+ *
+ * It's especially interesting to run this on CPU0.
+ */
+
+unsigned short selector;
+
+static void badds(void)
+{
+ __asm__ volatile("movw %0, %%ds" : : "r" (selector));
+}
+
+static void bades(void)
+{
+ __asm__ volatile("movw %0, %%es" : : "r" (selector));
+}
+
+static void badfs(void)
+{
+ __asm__ volatile("movw %0, %%fs" : : "r" (selector));
+}
+
+static void badgs(void)
+{
+ __asm__ volatile("movw %0, %%gs" : : "r" (selector));
+}
+
+static void badss(void)
+{
+ __asm__ volatile("movw %0, %%ss" : : "r" (selector));
+}
+
+static void
+resetseg(uint_t seg)
+{
+ ucontext_t ucp;
+ int done = 0;
+
+ int rc = getcontext(&ucp);
+ if (done) {
+ rc = getcontext(&ucp);
+ return;
+ }
+
+ done = 1;
+ ucp.uc_mcontext.gregs[seg] = selector;
+ setcontext(&ucp);
+ abort();
+}
+
+static void
+resetcs(void)
+{
+ return (resetseg(CS));
+}
+
+static void
+resetds(void)
+{
+ return (resetseg(DS));
+}
+
+static void
+resetes(void)
+{
+ return (resetseg(ES));
+}
+
+static void
+resetfs(void)
+{
+ return (resetseg(FS));
+}
+
+static void
+resetgs(void)
+{
+ return (resetseg(GS));
+}
+
+static void
+resetss(void)
+{
+ return (resetseg(SS));
+}
+
+static void
+inchild(void (*func)())
+{
+ pid_t pid;
+
+ switch ((pid = fork())) {
+ case 0:
+ func();
+ exit(0);
+ case -1:
+ exit(1);
+ default:
+ (void) waitpid(pid, NULL, 0);
+ return;
+ }
+
+}
+
+int
+main(int argc, char *argv[])
+{
+ for (selector = 0; selector < 8194; selector++) {
+ inchild(resetcs);
+ inchild(resetds);
+ inchild(resetes);
+ inchild(resetfs);
+ inchild(resetgs);
+ inchild(resetss);
+ inchild(badds);
+ inchild(bades);
+ inchild(badfs);
+ inchild(badgs);
+ inchild(badss);
+ }
+
+ exit(0);
+}
diff --git a/usr/src/uts/intel/ia32/os/desctbls.c b/usr/src/uts/intel/ia32/os/desctbls.c
index ef733f648f..8a6ae25a70 100644
--- a/usr/src/uts/intel/ia32/os/desctbls.c
+++ b/usr/src/uts/intel/ia32/os/desctbls.c
@@ -1290,6 +1290,28 @@ init_desctbls(void)
#endif /* __xpv */
+#ifndef __xpv
+/*
+ * As per Intel Vol 3 27.5.2, the GDTR limit is reset to 64Kb on a VM exit, so
+ * we have to manually fix it up ourselves.
+ *
+ * The caller may still need to make sure that it can't go off-CPU with the
+ * incorrect limit, before calling this (such as disabling pre-emption).
+ */
+void
+reset_gdtr_limit(void)
+{
+ ulong_t flags = intr_clear();
+ desctbr_t gdtr;
+
+ rd_gdtr(&gdtr);
+ gdtr.dtr_limit = (sizeof (user_desc_t) * NGDT) - 1;
+ wr_gdtr(&gdtr);
+
+ intr_restore(flags);
+}
+#endif /* __xpv */
+
/*
* In the early kernel, we need to set up a simple GDT to run on.
*
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index c90026f6fe..e550c1d063 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -891,6 +891,10 @@ extern void enable_pcid(void);
extern void xsave_setup_msr(struct cpu *);
+#if !defined(__xpv)
+extern void reset_gdtr_limit(void);
+#endif
+
/*
* Hypervisor signatures
*/