Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Mon, 12 Aug 2002 11:04:25 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Mon, 12 Aug 2002 11:04:24 -0400 Received: from mx2.elte.hu ([157.181.151.9]:46002 "HELO mx2.elte.hu") by vger.kernel.org with SMTP id ; Mon, 12 Aug 2002 11:04:18 -0400 Date: Mon, 12 Aug 2002 19:06:50 +0200 (CEST) From: Ingo Molnar Reply-To: Ingo Molnar To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, Alexandre Julliard , Luca Barbieri Subject: [patch] tls-2.5.31-D5 In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 20404 Lines: 656 okay, the attached patch does some more things: - moves the first two TLS entries and the user CS/DS entries on the same cacheline. - excludes CS/DS from the TLS space - Luca is right in that it only slows things down unnecesserily, and there is nothing that cannot be done by changing the %ds %cs selectors - and every cycle counts in the context-switch path. the only open issues are the number of TLSs supported. I'd vote for making them 4 and then we can inline the copy and make it unconditional, it will be 12 cycles to copy them all which alone is better than a branch miss. In this patch it's 2, thus the copying cost is 6 cycles. with 4 entries the 0x40 entry would be taken and APM has to move further up, and has to save/restore the 0x40 entry across BIOS calls. Ingo --- linux/drivers/pnp/pnpbios_core.c.orig Sun Aug 11 17:01:17 2002 +++ linux/drivers/pnp/pnpbios_core.c Mon Aug 12 17:01:11 2002 @@ -90,7 +90,8 @@ static union pnp_bios_expansion_header * pnp_bios_hdr = NULL; /* The PnP BIOS entries in the GDT */ -#define PNP_GDT (0x0060) +#define PNP_GDT (GDT_ENTRY_PNPBIOS_BASE * 8) + #define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */ #define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */ #define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */ --- linux/arch/i386/kernel/cpu/common.c.orig Sun Aug 11 17:01:06 2002 +++ linux/arch/i386/kernel/cpu/common.c Mon Aug 12 17:01:11 2002 @@ -423,6 +423,7 @@ { int cpu = smp_processor_id(); struct tss_struct * t = init_tss + cpu; + struct thread_struct *thread = ¤t->thread; if (test_and_set_bit(cpu, &cpu_initialized)) { printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); @@ -447,9 +448,13 @@ */ if (cpu) { memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE); - cpu_gdt_descr[cpu].size = GDT_SIZE; + cpu_gdt_descr[cpu].size = GDT_SIZE - 1; cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu]; } + /* + * Set up the per-thread TLS descriptor cache: + */ + memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_MAX * 8); __asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu])); __asm__ __volatile__("lidt %0": "=m" (idt_descr)); @@ -468,9 +473,9 @@ BUG(); enter_lazy_tlb(&init_mm, current, cpu); - t->esp0 = current->thread.esp0; + t->esp0 = thread->esp0; set_tss_desc(cpu,t); - cpu_gdt_table[cpu][TSS_ENTRY].b &= 0xfffffdff; + cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); load_LDT(&init_mm.context); --- linux/arch/i386/kernel/entry.S.orig Sun Aug 11 17:01:07 2002 +++ linux/arch/i386/kernel/entry.S Mon Aug 12 17:01:11 2002 @@ -753,6 +753,7 @@ .long sys_sched_setaffinity .long sys_sched_getaffinity .long sys_set_thread_area + .long sys_get_thread_area .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall --- linux/arch/i386/kernel/head.S.orig Sun Aug 11 17:01:06 2002 +++ linux/arch/i386/kernel/head.S Mon Aug 12 17:01:11 2002 @@ -239,12 +239,7 @@ movl %eax,%es movl %eax,%fs movl %eax,%gs -#ifdef CONFIG_SMP - movl $(__KERNEL_DS), %eax - movl %eax,%ss # Reload the stack pointer (segment only) -#else - lss stack_start,%esp # Load processor stack -#endif + movl %eax,%ss xorl %eax,%eax lldt %ax cld # gcc2 wants the direction flag cleared at all times @@ -412,17 +407,17 @@ ALIGN /* - * The Global Descriptor Table contains 20 quadwords, per-CPU. + * The Global Descriptor Table contains 28 quadwords, per-CPU. */ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x0000000000000000 /* TLS descriptor */ - .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ - .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ - .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ - .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ - .quad 0x0000000000000000 /* TSS descriptor */ - .quad 0x0000000000000000 /* LDT descriptor */ + .quad 0x0000000000000000 /* 0x0b reserved */ + .quad 0x0000000000000000 /* 0x13 reserved */ + .quad 0x0000000000000000 /* 0x1b reserved */ + .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ + .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ + .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ + .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ /* * The APM segments have byte granularity and their bases * and limits are set at run time. @@ -431,15 +426,21 @@ .quad 0x00409a0000000000 /* 0x48 APM CS code */ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ .quad 0x0040920000000000 /* 0x58 APM DS data */ + + .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ + .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ + .quad 0x0000000000000000 /* 0x70 TSS descriptor */ + .quad 0x0000000000000000 /* 0x78 LDT descriptor */ + /* Segments used for calling PnP BIOS */ - .quad 0x00c09a0000000000 /* 0x60 32-bit code */ - .quad 0x00809a0000000000 /* 0x68 16-bit code */ - .quad 0x0080920000000000 /* 0x70 16-bit data */ - .quad 0x0080920000000000 /* 0x78 16-bit data */ - .quad 0x0080920000000000 /* 0x80 16-bit data */ - .quad 0x0000000000000000 /* 0x88 not used */ - .quad 0x0000000000000000 /* 0x90 not used */ - .quad 0x0000000000000000 /* 0x98 not used */ + .quad 0x00c09a0000000000 /* 0x80 32-bit code */ + .quad 0x00809a0000000000 /* 0x88 16-bit code */ + .quad 0x0080920000000000 /* 0x90 16-bit data */ + .quad 0x0080920000000000 /* 0x98 16-bit data */ + .quad 0x0080920000000000 /* 0xa0 16-bit data */ + .quad 0x0000000000000000 /* 0xa8 not used */ + .quad 0x0000000000000000 /* 0xb0 not used */ + .quad 0x0000000000000000 /* 0xb8 not used */ #if CONFIG_SMP .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */ --- linux/arch/i386/kernel/process.c.orig Sun Aug 11 17:01:08 2002 +++ linux/arch/i386/kernel/process.c Mon Aug 12 17:01:11 2002 @@ -681,11 +681,9 @@ /* * Load the per-thread Thread-Local Storage descriptor. - * - * NOTE: it's faster to do the two stores unconditionally - * than to branch away. */ - load_TLS_desc(next, cpu); + if (prev->private_tls || next->private_tls) + load_TLS(next, cpu); /* * Save away %fs and %gs. No need to save %es and %ds, as @@ -834,35 +832,125 @@ #undef first_sched /* - * Set the Thread-Local Storage area: + * sys_alloc_thread_area: get a yet unused TLS descriptor index. */ -asmlinkage int sys_set_thread_area(unsigned long base, unsigned long flags) +static int get_free_idx(void) { struct thread_struct *t = ¤t->thread; - int writable = 0; - int cpu; + int idx; - /* do not allow unused flags */ - if (flags & ~TLS_FLAGS_MASK) + for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) + if (desc_empty(t->tls_array + idx)) + return idx + GDT_ENTRY_TLS_MIN; + return -ESRCH; +} + +static inline int private_tls(struct desc_struct *array) +{ + int idx; + + for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) + if (!desc_empty(array + idx)) + return 0; + return 1; +} + +/* + * Set a given TLS descriptor: + */ +asmlinkage int sys_set_thread_area(struct modify_ldt_ldt_s *u_info) +{ + struct thread_struct *t = ¤t->thread; + struct modify_ldt_ldt_s info; + struct desc_struct *desc; + int cpu, idx; + + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + idx = info.entry_number; + + /* + * index -1 means the kernel should try to find and + * allocate an empty descriptor: + */ + if (idx == -1) { + idx = get_free_idx(); + if (idx < 0) + return idx; + if (put_user(idx, &u_info->entry_number)) + return -EFAULT; + } + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) return -EINVAL; - if (flags & TLS_FLAG_WRITABLE) - writable = 1; + desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN; /* * We must not get preempted while modifying the TLS. */ cpu = get_cpu(); - t->tls_desc.a = ((base & 0x0000ffff) << 16) | 0xffff; - - t->tls_desc.b = (base & 0xff000000) | ((base & 0x00ff0000) >> 16) | - 0xf0000 | (writable << 9) | (1 << 15) | - (1 << 22) | (1 << 23) | 0x7000; + if (LDT_empty(&info)) { + desc->a = 0; + desc->b = 0; + } else { + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + } + t->private_tls = private_tls(t->tls_array); + load_TLS(t, cpu); - load_TLS_desc(t, cpu); put_cpu(); - return TLS_ENTRY*8 + 3; + return 0; +} + +/* + * Get the current Thread-Local Storage area: + */ + +#define GET_BASE(desc) ( \ + (((desc)->a >> 16) & 0x0000ffff) | \ + (((desc)->b << 16) & 0x00ff0000) | \ + ( (desc)->b & 0xff000000) ) + +#define GET_LIMIT(desc) ( \ + ((desc)->a & 0x0ffff) | \ + ((desc)->b & 0xf0000) ) + +#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) +#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) +#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) +#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) +#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) + +asmlinkage int sys_get_thread_area(struct modify_ldt_ldt_s *u_info) +{ + struct modify_ldt_ldt_s info; + struct desc_struct *desc; + int idx; + + if (get_user(idx, &u_info->entry_number)) + return -EFAULT; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; + + info.entry_number = idx; + info.base_addr = GET_BASE(desc); + info.limit = GET_LIMIT(desc); + info.seg_32bit = GET_32BIT(desc); + info.contents = GET_CONTENTS(desc); + info.read_exec_only = !GET_WRITABLE(desc); + info.limit_in_pages = GET_LIMIT_PAGES(desc); + info.seg_not_present = !GET_PRESENT(desc); + info.useable = GET_USEABLE(desc); + + if (copy_to_user(u_info, &info, sizeof(info))) + return -EFAULT; + return 0; } --- linux/arch/i386/kernel/suspend.c.orig Sun Aug 11 17:01:06 2002 +++ linux/arch/i386/kernel/suspend.c Mon Aug 12 17:01:11 2002 @@ -207,7 +207,7 @@ struct tss_struct * t = init_tss + cpu; set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy tsc or some similar stupidity. */ - cpu_gdt_table[cpu][TSS_ENTRY].b &= 0xfffffdff; + cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); /* This does ltr */ load_LDT(¤t->mm->context); /* This does lldt */ --- linux/arch/i386/kernel/ldt.c.orig Sun Aug 11 17:01:04 2002 +++ linux/arch/i386/kernel/ldt.c Mon Aug 12 17:01:11 2002 @@ -200,32 +200,17 @@ /* Allow LDTs to be cleared by the user. */ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { - if (oldmode || - (ldt_info.contents == 0 && - ldt_info.read_exec_only == 1 && - ldt_info.seg_32bit == 0 && - ldt_info.limit_in_pages == 0 && - ldt_info.seg_not_present == 1 && - ldt_info.useable == 0 )) { + if (oldmode || LDT_empty(&ldt_info)) { entry_1 = 0; entry_2 = 0; goto install; } } - entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | - (ldt_info.limit & 0x0ffff); - entry_2 = (ldt_info.base_addr & 0xff000000) | - ((ldt_info.base_addr & 0x00ff0000) >> 16) | - (ldt_info.limit & 0xf0000) | - ((ldt_info.read_exec_only ^ 1) << 9) | - (ldt_info.contents << 10) | - ((ldt_info.seg_not_present ^ 1) << 15) | - (ldt_info.seg_32bit << 22) | - (ldt_info.limit_in_pages << 23) | - 0x7000; - if (!oldmode) - entry_2 |= (ldt_info.useable << 20); + entry_1 = LDT_entry_a(&ldt_info); + entry_2 = LDT_entry_b(&ldt_info); + if (oldmode) + entry_2 &= ~(1 << 20); /* Install the new entry ... */ install: --- linux/arch/i386/boot/setup.S.orig Sun Jun 9 07:26:32 2002 +++ linux/arch/i386/boot/setup.S Mon Aug 12 17:01:11 2002 @@ -1005,9 +1005,14 @@ ret # Descriptor tables +# +# NOTE: if you think the GDT is large, you can make it smaller by just +# defining the KERNEL_CS and KERNEL_DS entries and shifting the gdt +# address down by GDT_ENTRY_KERNEL_CS*8. This puts bogus entries into +# the GDT, but those wont be used so it's not a problem. +# gdt: - .word 0, 0, 0, 0 # dummy - .word 0, 0, 0, 0 # unused + .fill GDT_ENTRY_KERNEL_CS,8,0 .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) .word 0 # base address = 0 --- linux/include/linux/apm_bios.h.orig Sun Jun 9 07:30:24 2002 +++ linux/include/linux/apm_bios.h Mon Aug 12 17:01:11 2002 @@ -21,8 +21,8 @@ #ifdef __KERNEL__ -#define APM_40 0x40 -#define APM_CS (APM_40 + 8) +#define APM_40 (GDT_ENTRY_APMBIOS_BASE * 8) +#define APM_CS (APM_BASE + 8) #define APM_CS_16 (APM_CS + 8) #define APM_DS (APM_CS_16 + 8) --- linux/include/asm-i386/desc.h.orig Sun Aug 11 17:01:07 2002 +++ linux/include/asm-i386/desc.h Mon Aug 12 17:01:11 2002 @@ -2,50 +2,12 @@ #define __ARCH_DESC_H #include - -/* - * The layout of the per-CPU GDT under Linux: - * - * 0 - null - * 1 - Thread-Local Storage (TLS) segment - * 2 - kernel code segment - * 3 - kernel data segment - * 4 - user code segment <==== new cacheline - * 5 - user data segment - * 6 - TSS - * 7 - LDT - * 8 - APM BIOS support <==== new cacheline - * 9 - APM BIOS support - * 10 - APM BIOS support - * 11 - APM BIOS support - * 12 - PNPBIOS support <==== new cacheline - * 13 - PNPBIOS support - * 14 - PNPBIOS support - * 15 - PNPBIOS support - * 16 - PNPBIOS support <==== new cacheline - * 17 - not used - * 18 - not used - * 19 - not used - */ -#define TLS_ENTRY 1 -#define TSS_ENTRY 6 -#define LDT_ENTRY 7 -/* - * The interrupt descriptor table has room for 256 idt's, - * the global descriptor table is dependent on the number - * of tasks we can have.. - * - * We pad the GDT to cacheline boundary. - */ -#define IDT_ENTRIES 256 -#define GDT_ENTRIES 20 +#include #ifndef __ASSEMBLY__ #include -#define GDT_SIZE (GDT_ENTRIES*sizeof(struct desc_struct)) - extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES]; struct Xgt_desc_struct { @@ -55,8 +17,8 @@ extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS]; -#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (TSS_ENTRY<<3)) -#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (LDT_ENTRY<<3)) +#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8)) +#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8)) /* * This is the ldt that every process will get unless we need @@ -78,21 +40,48 @@ static inline void set_tss_desc(unsigned int cpu, void *addr) { - _set_tssldt_desc(&cpu_gdt_table[cpu][TSS_ENTRY], (int)addr, 235, 0x89); + _set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (int)addr, 235, 0x89); } static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size) { - _set_tssldt_desc(&cpu_gdt_table[cpu][LDT_ENTRY], (int)addr, ((size << 3)-1), 0x82); + _set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); } -#define TLS_FLAGS_MASK 0x00000001 +#define LDT_entry_a(info) \ + ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) -#define TLS_FLAG_WRITABLE 0x00000001 +#define LDT_entry_b(info) \ + (((info)->base_addr & 0xff000000) | \ + (((info)->base_addr & 0x00ff0000) >> 16) | \ + ((info)->limit & 0xf0000) | \ + (((info)->read_exec_only ^ 1) << 9) | \ + ((info)->contents << 10) | \ + (((info)->seg_not_present ^ 1) << 15) | \ + ((info)->seg_32bit << 22) | \ + ((info)->limit_in_pages << 23) | \ + ((info)->useable << 20) | \ + 0x7000) + +#define LDT_empty(info) (\ + (info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ + (info)->read_exec_only == 1 && \ + (info)->seg_32bit == 0 && \ + (info)->limit_in_pages == 0 && \ + (info)->seg_not_present == 1 && \ + (info)->useable == 0 ) + +#if TLS_SIZE != 16 +# error update this code. +#endif -static inline void load_TLS_desc(struct thread_struct *t, unsigned int cpu) +static inline void load_TLS(struct thread_struct *t, unsigned int cpu) { - cpu_gdt_table[cpu][TLS_ENTRY] = t->tls_desc; +#define C(i) cpu_gdt_table[cpu][GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] + C(0); C(1); +#undef C } static inline void clear_LDT(void) --- linux/include/asm-i386/processor.h.orig Sun Aug 11 17:01:07 2002 +++ linux/include/asm-i386/processor.h Mon Aug 12 17:01:11 2002 @@ -22,6 +22,11 @@ unsigned long a,b; }; +#define desc_empty(desc) \ + (!((desc)->a + (desc)->b)) + +#define desc_equal(desc1, desc2) \ + (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b)) /* * Default implementation of macro that returns current * instruction pointer ("program counter"). @@ -376,8 +381,16 @@ unsigned long v86flags, v86mask, v86mode, saved_esp0; /* IO permissions */ unsigned long *ts_io_bitmap; -/* TLS cached descriptor */ - struct desc_struct tls_desc; + + /* + * cached TLS descriptors. + * + * The offset calculation is needed to not copy the whole TLS + * into the local GDT all the time. + * We count offsets in bytes to reduce context-switch overhead. + */ + int private_tls; + struct desc_struct tls_array[GDT_ENTRY_TLS_MAX + 1]; }; #define INIT_THREAD { \ @@ -401,7 +414,7 @@ 0,0,0,0, /* esp,ebp,esi,edi */ \ 0,0,0,0,0,0, /* es,cs,ss */ \ 0,0,0,0,0,0, /* ds,fs,gs */ \ - LDT_ENTRY,0, /* ldt */ \ + GDT_ENTRY_LDT,0, /* ldt */ \ 0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \ {~0, } /* ioperm */ \ } --- linux/include/asm-i386/segment.h.orig Sun Jun 9 07:28:19 2002 +++ linux/include/asm-i386/segment.h Mon Aug 12 17:01:11 2002 @@ -1,10 +1,79 @@ #ifndef _ASM_SEGMENT_H #define _ASM_SEGMENT_H -#define __KERNEL_CS 0x10 -#define __KERNEL_DS 0x18 +/* + * The layout of the per-CPU GDT under Linux: + * + * 0 - null + * 1 - reserved + * 2 - reserved + * 3 - reserved + * + * 4 - default user CS <==== new cacheline + * 5 - default user DS + * + * ------- start of TLS (Thread-Local Storage) segments: + * + * 6 - TLS segment #1 [ glibc's TLS segment ] + * 7 - TLS segment #2 [ Wine's %fs Win32 segment ] + * + * ------- start of kernel segments: + * + * 8 - APM BIOS support [ segment 0x40 ] + * 9 - APM BIOS support + * 10 - APM BIOS support + * 11 - APM BIOS support + * 12 - kernel code segment <==== new cacheline + * 13 - kernel data segment + * 14 - TSS + * 15 - LDT + * 16 - PNPBIOS support (16->32 gate) + * 17 - PNPBIOS support + * 18 - PNPBIOS support + * 19 - PNPBIOS support + * 20 - PNPBIOS support + * 21 - reserved + * 22 - reserved + * 23 - reserved + */ +#define GDT_ENTRY_TLS_ENTRIES 2 +#define GDT_ENTRY_TLS_MIN 6 +#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) -#define __USER_CS 0x23 -#define __USER_DS 0x2B +#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) + +#define GDT_ENTRY_DEFAULT_USER_CS 4 +#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3) + +#define GDT_ENTRY_DEFAULT_USER_DS 5 +#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3) + +#define GDT_ENTRY_KERNEL_BASE 8 + +#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 0) +#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 4) +#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8) + +#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 5) +#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8) + +#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE + 6) +#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE + 7) + +#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 8) + +/* + * The GDT has 21 entries but we pad it to cacheline boundary: + */ +#define GDT_ENTRIES 24 + +#define GDT_SIZE (GDT_ENTRIES * 8) + +/* + * The interrupt descriptor table has room for 256 idt's, + * the global descriptor table is dependent on the number + * of tasks we can have.. + */ +#define IDT_ENTRIES 256 #endif --- linux/include/asm-i386/unistd.h.orig Sun Aug 11 17:01:07 2002 +++ linux/include/asm-i386/unistd.h Mon Aug 12 17:01:11 2002 @@ -248,6 +248,7 @@ #define __NR_sched_setaffinity 241 #define __NR_sched_getaffinity 242 #define __NR_set_thread_area 243 +#define __NR_get_thread_area 244 /* user-visible error numbers are in the range -1 - -124: see */ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/