Skip to content

Commit

Permalink
9723 provide support for VMM's GDT handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
John Levon authored and Dan McDonald committed Aug 13, 2018
1 parent 734b3a4 commit 309b04b
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 50 deletions.
12 changes: 10 additions & 2 deletions usr/src/cmd/mdb/i86pc/modules/unix/unix.c
Expand Up @@ -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 },
Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand Down Expand Up @@ -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 }
};
Expand Down
2 changes: 2 additions & 0 deletions usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.h
Expand Up @@ -21,6 +21,7 @@
*/

#include <sys/types.h>
#include <sys/segments.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -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
}
Expand Down
47 changes: 7 additions & 40 deletions usr/src/cmd/mdb/i86pc/modules/unix/unix_sup.s
Expand Up @@ -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
Expand All @@ -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 */
1 change: 1 addition & 0 deletions usr/src/pkg/manifests/system-test-ostest.mf
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion usr/src/test/os-tests/runfiles/default.run
Expand Up @@ -66,4 +66,4 @@ tests = ['acquire-compare', 'acquire-spray']
[/opt/os-tests/tests/i386]
user = root
arch = i86pc
tests = ['ldt']
tests = ['ldt', 'badseg']
15 changes: 8 additions & 7 deletions usr/src/test/os-tests/tests/i386/Makefile
Expand Up @@ -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)
Expand Down
146 changes: 146 additions & 0 deletions 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);
}
22 changes: 22 additions & 0 deletions usr/src/uts/intel/ia32/os/desctbls.c
Expand Up @@ -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.
*
Expand Down
4 changes: 4 additions & 0 deletions usr/src/uts/intel/sys/x86_archext.h
Expand Up @@ -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
*/
Expand Down

0 comments on commit 309b04b

Please sign in to comment.