Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add most of my USER_LDT code for amd64, but disable...
details: https://anonhg.NetBSD.org/src/rev/4c95610926d2
branches: trunk
changeset: 351466:4c95610926d2
user: maxv <maxv%NetBSD.org@localhost>
date: Tue Feb 14 09:11:05 2017 +0000
description:
Add most of my USER_LDT code for amd64, but disable it and put a comment
about why Wine still does not work.
Nothing changes, but at least it is a step forward.
diffstat:
sys/arch/amd64/amd64/trap.c | 8 ++++-
sys/arch/x86/x86/sys_machdep.c | 59 +++++++++++++++++++++++++++++++++++++----
2 files changed, 59 insertions(+), 8 deletions(-)
diffs (180 lines):
diff -r 0fe04840a3fa -r 4c95610926d2 sys/arch/amd64/amd64/trap.c
--- a/sys/arch/amd64/amd64/trap.c Tue Feb 14 09:07:35 2017 +0000
+++ b/sys/arch/amd64/amd64/trap.c Tue Feb 14 09:11:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.89 2017/01/18 05:11:59 kamil Exp $ */
+/* $NetBSD: trap.c,v 1.90 2017/02/14 09:11:05 maxv Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.89 2017/01/18 05:11:59 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.90 2017/02/14 09:11:05 maxv Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -373,6 +373,10 @@
break;
case 0x848e: /* mov 0xa8(%rsp),%es (8e 84 24 a8 00 00 00) */
case 0x9c8e: /* mov 0xb0(%rsp),%ds (8e 9c 24 b0 00 00 00) */
+#ifdef USER_LDT
+ case 0xa48e: /* mov 0xa0(%rsp),%fs (8e a4 24 a0 00 00 00) */
+ case 0xac8e: /* mov 0x98(%rsp),%gs (8e ac 24 98 00 00 00) */
+#endif
/*
* We faulted loading one of the user segment registers.
* The stack frame containing the user registers is
diff -r 0fe04840a3fa -r 4c95610926d2 sys/arch/x86/x86/sys_machdep.c
--- a/sys/arch/x86/x86/sys_machdep.c Tue Feb 14 09:07:35 2017 +0000
+++ b/sys/arch/x86/x86/sys_machdep.c Tue Feb 14 09:11:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_machdep.c,v 1.31 2017/02/05 10:42:21 maxv Exp $ */
+/* $NetBSD: sys_machdep.c,v 1.32 2017/02/14 09:11:05 maxv Exp $ */
/*-
* Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.31 2017/02/05 10:42:21 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.32 2017/02/14 09:11:05 maxv Exp $");
#include "opt_mtrr.h"
#include "opt_perfctrs.h"
@@ -68,8 +68,23 @@
#include <machine/mtrr.h>
#ifdef __x86_64__
+/*
+ * The code for USER_LDT on amd64 is mostly functional, but it is still not
+ * enabled.
+ *
+ * On amd64 we are allowing only 8-byte-sized entries in the LDT, and we are
+ * not allowing the user to overwrite the existing entries (below LDT_SIZE).
+ * Note that USER_LDT is used only by 32bit applications, under compat_netbsd32.
+ * This is theoretically enough for Wine to work.
+ *
+ * However, letting segment registers have different location breaks amd64's
+ * Thread Local Storage: %fs and %gs must be reloaded when returning to
+ * userland. See the tech-kern@ archive from February 2017. A patch has been
+ * proposed to fix that, but Wine still randomly crashes; it is not clear
+ * whether the issues come from Wine, from netbsd32 or from the patch itself.
+ */
+#undef USER_LDT
/* Need to be checked. */
-#undef USER_LDT
#undef PERFCTRS
#undef IOPERM
#else
@@ -168,14 +183,23 @@
ua->start + ua->num > 8192)
return (EINVAL);
+#ifdef __x86_64__
+ if (ua->start * sizeof(union descriptor) < LDT_SIZE)
+ return EINVAL;
+#endif
+
mutex_enter(&cpu_lock);
if (pmap->pm_ldt != NULL) {
nldt = pmap->pm_ldt_len / sizeof(*lp);
lp = pmap->pm_ldt;
} else {
+#ifdef __x86_64__
+ nldt = LDT_SIZE / sizeof(*lp);
+#else
nldt = NLDT;
- lp = ldtstore;
+#endif
+ lp = (union descriptor *)ldtstore;
}
if (ua->start > nldt) {
@@ -244,6 +268,12 @@
size_t old_len, new_len;
union descriptor *old_ldt, *new_ldt;
+#ifdef __x86_64__
+ const size_t min_ldt_size = LDT_SIZE;
+#else
+ const size_t min_ldt_size = NLDT * sizeof(union descriptor);
+#endif
+
error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_LDT_SET,
NULL, NULL, NULL, NULL);
if (error)
@@ -253,6 +283,11 @@
ua->start + ua->num > 8192)
return (EINVAL);
+#ifdef __x86_64__
+ if (ua->start * sizeof(union descriptor) < LDT_SIZE)
+ return EINVAL;
+#endif
+
/* Check descriptors for access violations. */
for (i = 0; i < ua->num; i++) {
union descriptor *desc = &descv[i];
@@ -261,6 +296,12 @@
case SDT_SYSNULL:
desc->sd.sd_p = 0;
break;
+#ifdef __x86_64__
+ case SDT_SYS286CGT:
+ case SDT_SYS386CGT:
+ /* We don't allow these on amd64. */
+ return EACCES;
+#else
case SDT_SYS286CGT:
case SDT_SYS386CGT:
/*
@@ -277,6 +318,7 @@
return EACCES;
}
break;
+#endif
case SDT_MEMEC:
case SDT_MEMEAC:
case SDT_MEMERC:
@@ -324,7 +366,7 @@
for (;;) {
new_len = (ua->start + ua->num) * sizeof(union descriptor);
new_len = max(new_len, pmap->pm_ldt_len);
- new_len = max(new_len, NLDT * sizeof(union descriptor));
+ new_len = max(new_len, min_ldt_size);
new_len = round_page(new_len);
new_ldt = (union descriptor *)uvm_km_alloc(kernel_map,
new_len, 0, UVM_KMF_WIRED | UVM_KMF_ZERO | UVM_KMF_WAITVA);
@@ -347,7 +389,7 @@
old_ldt = NULL;
old_len = 0;
old_sel = -1;
- memcpy(new_ldt, ldtstore, NLDT * sizeof(union descriptor));
+ memcpy(new_ldt, ldtstore, min_ldt_size);
}
/* Apply requested changes. */
@@ -768,6 +810,10 @@
error = x86_iopl(l, SCARG(uap, parms), retval);
break;
+#ifdef i386
+ /*
+ * On amd64, this is done via netbsd32_sysarch.
+ */
case X86_GET_LDT:
error = x86_get_ldt(l, SCARG(uap, parms), retval);
break;
@@ -775,6 +821,7 @@
case X86_SET_LDT:
error = x86_set_ldt(l, SCARG(uap, parms), retval);
break;
+#endif
case X86_GET_IOPERM:
error = x86_get_ioperm(l, SCARG(uap, parms), retval);
Home |
Main Index |
Thread Index |
Old Index