Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch add the guts of TLS support on amd64. based on joe...
details: https://anonhg.NetBSD.org/src/rev/125dc7eee639
branches: trunk
changeset: 756121:125dc7eee639
user: chs <chs%NetBSD.org@localhost>
date: Wed Jul 07 01:14:52 2010 +0000
description:
add the guts of TLS support on amd64. based on joerg's patch,
reworked by me to support 32-bit processes as well.
we now keep %fs and %gs loaded with the user values
while in the kernel, which means we don't need to
reload them when returning to user mode.
diffstat:
sys/arch/amd64/amd64/cpufunc.S | 15 +++-
sys/arch/amd64/amd64/gdt.c | 134 ++++++++++++++-----------------
sys/arch/amd64/amd64/genassym.cf | 8 +-
sys/arch/amd64/amd64/locore.S | 65 ++++++++++++--
sys/arch/amd64/amd64/machdep.c | 119 ++++++++++++++++++++++++++-
sys/arch/amd64/amd64/netbsd32_machdep.c | 62 ++++++++-----
sys/arch/amd64/amd64/vector.S | 6 +-
sys/arch/amd64/include/frameasm.h | 13 +-
sys/arch/amd64/include/gdt.h | 7 +-
sys/arch/amd64/include/pcb.h | 7 +-
sys/arch/amd64/include/segments.h | 19 +++-
sys/arch/x86/include/cpufunc.h | 4 +-
sys/arch/x86/include/sysarch.h | 12 +-
sys/arch/x86/x86/pmap.c | 14 +--
14 files changed, 322 insertions(+), 163 deletions(-)
diffs (truncated from 1010 to 300 lines):
diff -r c4bae5f113be -r 125dc7eee639 sys/arch/amd64/amd64/cpufunc.S
--- a/sys/arch/amd64/amd64/cpufunc.S Wed Jul 07 01:13:29 2010 +0000
+++ b/sys/arch/amd64/amd64/cpufunc.S Wed Jul 07 01:14:52 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.S,v 1.16 2009/10/01 09:13:54 skrll Exp $ */
+/* $NetBSD: cpufunc.S,v 1.17 2010/07/07 01:14:52 chs Exp $ */
/*-
* Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -34,6 +34,7 @@
*/
#include <machine/asm.h>
+#include <machine/frameasm.h>
#include <machine/specialreg.h>
#include <machine/segments.h>
@@ -513,3 +514,15 @@
rep
outsl
ret
+
+ENTRY(setfs)
+ movw %di, %fs
+ ret
+
+ENTRY(setusergs)
+ CLI(ax)
+ swapgs
+ movw %di, %gs
+ swapgs
+ STI(ax)
+ ret
diff -r c4bae5f113be -r 125dc7eee639 sys/arch/amd64/amd64/gdt.c
--- a/sys/arch/amd64/amd64/gdt.c Wed Jul 07 01:13:29 2010 +0000
+++ b/sys/arch/amd64/amd64/gdt.c Wed Jul 07 01:14:52 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gdt.c,v 1.23 2009/11/21 03:11:01 rmind Exp $ */
+/* $NetBSD: gdt.c,v 1.24 2010/07/07 01:14:52 chs Exp $ */
/*-
* Copyright (c) 1996, 1997, 2009 The NetBSD Foundation, Inc.
@@ -37,10 +37,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.23 2009/11/21 03:11:01 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.24 2010/07/07 01:14:52 chs Exp $");
#include "opt_multiprocessor.h"
#include "opt_xen.h"
+#include "opt_user_ldt.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -56,7 +57,6 @@
#include <xen/hypervisor.h>
#endif
-
int gdt_size; /* size of GDT in bytes */
int gdt_dyncount; /* number of dyn. allocated GDT entries in use */
int gdt_dynavail;
@@ -69,48 +69,45 @@
void gdt_put_slot(int);
void
-set_mem_gdt(struct mem_segment_descriptor *sd, void *base, size_t limit,
- int type, int dpl, int gran, int def32, int is64)
+update_descriptor(void *tp, void *ep)
{
-#if 0
- CPU_INFO_ITERATOR cii;
- struct cpu_info *ci;
- int off;
-#endif
+ uint64_t *table, *entry;
+
+ table = tp;
+ entry = ep;
- set_mem_segment(sd, base, limit, type, dpl, gran, def32, is64);
-#if 0
- off = (char *)sd - gdtstore;
- for (CPU_INFO_FOREACH(cii, ci)) {
- if (ci->ci_gdt != NULL)
- *(struct mem_segment_descriptor *)(ci->ci_gdt + off) =
- *sd;
- }
+#ifndef XEN
+ *table = *entry;
+#else
+ paddr_t pa;
+
+ if (!pmap_extract_ma(pmap_kernel(), (vaddr_t)table, &pa) ||
+ HYPERVISOR_update_descriptor(pa, *entry))
+ panic("HYPERVISOR_update_descriptor failed\n");
#endif
}
void
-set_sys_gdt(struct sys_segment_descriptor *sd, void *base, size_t limit,
+set_sys_gdt(int slot, void *base, size_t limit,
int type, int dpl, int gran)
{
-#if 0
+ union {
+ struct sys_segment_descriptor sd;
+ uint64_t bits[2];
+ } d;
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
- int off;
-#endif
+ int idx;
- set_sys_segment(sd, base, limit, type, dpl, gran);
-#if 0
- off = (char *)sd - gdtstore;
+ set_sys_segment(&d.sd, base, limit, type, dpl, gran);
+ idx = IDXSEL(GDYNSEL(slot, SEL_KPL));
for (CPU_INFO_FOREACH(cii, ci)) {
- if (ci->ci_gdt != NULL)
- *(struct sys_segment_descriptor *)(ci->ci_gdt + off) =
- *sd;
+ KASSERT(ci->ci_gdt != NULL);
+ update_descriptor(&ci->ci_gdt[idx + 0], &d.bits[0]);
+ update_descriptor(&ci->ci_gdt[idx + 1], &d.bits[1]);
}
-#endif
}
-
/*
* Initialize the GDT.
*/
@@ -157,16 +154,25 @@
void
gdt_alloc_cpu(struct cpu_info *ci)
{
-#if 0
- ci->ci_gdt = (void *)uvm_km_valloc(kernel_map, MAXGDTSIZ);
- uvm_map_pageable(kernel_map, (vaddr_t)ci->ci_gdt,
- (vaddr_t)ci->ci_gdt + MINGDTSIZ, false, false);
- memset(ci->ci_gdt, 0, MINGDTSIZ);
- memcpy(ci->ci_gdt, gdtstore,
- DYNSEL_START + gdt_dyncount * sizeof(struct sys_segment_descriptor));
-#else
- ci->ci_gdt = (void *)gdtstore;
-#endif
+ int max_len = MAXGDTSIZ;
+ int min_len = MINGDTSIZ;
+ struct vm_page *pg;
+ vaddr_t va;
+
+ ci->ci_gdt = (union descriptor *)uvm_km_alloc(kernel_map, max_len,
+ 0, UVM_KMF_VAONLY);
+ for (va = (vaddr_t)ci->ci_gdt; va < (vaddr_t)ci->ci_gdt + min_len;
+ va += PAGE_SIZE) {
+ while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO))
+ == NULL) {
+ uvm_wait("gdt_alloc_cpu");
+ }
+ pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ | VM_PROT_WRITE, 0);
+ }
+ pmap_update(pmap_kernel());
+ memset(ci->ci_gdt, 0, min_len);
+ memcpy(ci->ci_gdt, gdtstore, gdt_size);
}
@@ -182,14 +188,12 @@
#ifndef XEN
setregion(®ion, ci->ci_gdt, (uint16_t)(MAXGDTSIZ - 1));
#else
- /* Enter only allocated frames */
setregion(®ion, ci->ci_gdt, (uint16_t)(gdt_size - 1));
#endif
lgdt(®ion);
}
#ifdef MULTIPROCESSOR
-
void
gdt_reload_cpu(struct cpu_info *ci)
{
@@ -198,7 +202,6 @@
#ifndef XEN
setregion(®ion, ci->ci_gdt, MAXGDTSIZ - 1);
#else
- /* Enter only allocated frames */
setregion(®ion, ci->ci_gdt, gdt_size - 1);
#endif
lgdt(®ion);
@@ -303,28 +306,9 @@
mutex_enter(&cpu_lock);
slot = gdt_get_slot();
-#if 0
- printf("tss_alloc: slot %d addr %p\n", slot, &gdt[slot]);
-#endif
- set_sys_gdt(&gdt[slot], tss, sizeof (struct x86_64_tss)-1,
+ set_sys_gdt(slot, tss, sizeof (struct x86_64_tss) - 1,
SDT_SYS386TSS, SEL_KPL, 0);
mutex_exit(&cpu_lock);
-#if 0
- printf("lolimit %lx lobase %lx type %lx dpl %lx p %lx hilimit %lx\n"
- "xx1 %lx gran %lx hibase %lx xx2 %lx zero %lx xx3 %lx pad %lx\n",
- (unsigned long)gdt[slot].sd_lolimit,
- (unsigned long)gdt[slot].sd_lobase,
- (unsigned long)gdt[slot].sd_type,
- (unsigned long)gdt[slot].sd_dpl,
- (unsigned long)gdt[slot].sd_p,
- (unsigned long)gdt[slot].sd_hilimit,
- (unsigned long)gdt[slot].sd_xx1,
- (unsigned long)gdt[slot].sd_gran,
- (unsigned long)gdt[slot].sd_hibase,
- (unsigned long)gdt[slot].sd_xx2,
- (unsigned long)gdt[slot].sd_zero,
- (unsigned long)gdt[slot].sd_xx3);
-#endif
return GDYNSEL(slot, SEL_KPL);
#else /* XEN */
/* TSS, what for? */
@@ -344,6 +328,7 @@
#endif
}
+#ifdef USER_LDT
void
ldt_alloc(struct pmap *pmap, char *ldt, size_t len)
{
@@ -355,7 +340,7 @@
gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
slot = gdt_get_slot();
- set_sys_gdt(&gdt[slot], ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0);
+ set_sys_gdt(slot, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0);
pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
}
@@ -370,6 +355,7 @@
gdt_put_slot(slot);
}
+#endif
#ifdef XEN
void
@@ -380,22 +366,22 @@
vaddr_t va;
/*
- * XXX: Xen even checks descriptors AFTER limit.
- * Zero out last frame after limit if needed.
- */
+ * XXX: Xen even checks descriptors AFTER limit.
+ * Zero out last frame after limit if needed.
+ */
va = desc->rd_base + desc->rd_limit + 1;
__PRINTK(("memset 0x%lx -> 0x%lx\n", va, roundup(va, PAGE_SIZE)));
memset((void *) va, 0, roundup(va, PAGE_SIZE) - va);
- for (i = 0; i < roundup(desc->rd_limit,PAGE_SIZE) >> PAGE_SHIFT; i++) {
+ for (i = 0; i < roundup(desc->rd_limit, PAGE_SIZE) >> PAGE_SHIFT; i++) {
+
/*
- * The lgdt instr uses virtual addresses, do some translation fo
-r Xen.
- * Mark pages R/O too, else Xen will refuse to use them
- */
+ * The lgdt instruction uses virtual addresses,
+ * do some translation for Xen.
+ * Mark pages R/O too, else Xen will refuse to use them.
+ */
frames[i] = ((paddr_t) xpmap_ptetomach(
- (pt_entry_t *) (desc->rd_base + (i << PAGE_SHIFT
-))))
+ (pt_entry_t *) (desc->rd_base + (i << PAGE_SHIFT))))
>> PAGE_SHIFT;
__PRINTK(("frames[%d] = 0x%lx (pa 0x%lx)\n", i, frames[i],
xpmap_mtop(frames[i] << PAGE_SHIFT)));
diff -r c4bae5f113be -r 125dc7eee639 sys/arch/amd64/amd64/genassym.cf
--- a/sys/arch/amd64/amd64/genassym.cf Wed Jul 07 01:13:29 2010 +0000
+++ b/sys/arch/amd64/amd64/genassym.cf Wed Jul 07 01:14:52 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.44 2010/04/28 19:17:03 dyoung Exp $
+# $NetBSD: genassym.cf,v 1.45 2010/07/07 01:14:52 chs Exp $
#
# Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -188,6 +188,10 @@
define PCB_CR0 offsetof(struct pcb, pcb_cr0)
define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
define PCB_FPCPU offsetof(struct pcb, pcb_fpcpu)
+define PCB_FLAGS offsetof(struct pcb, pcb_flags)
+define PCB_COMPAT32 PCB_COMPAT32
+define PCB_FS offsetof(struct pcb, pcb_fs)
+define PCB_GS offsetof(struct pcb, pcb_gs)
Home |
Main Index |
Thread Index |
Old Index