2008-01-30 15:31:09 +03:00
# ifndef _ASM_X86_SEGMENT_H_
# define _ASM_X86_SEGMENT_H_
2008-07-17 22:29:24 +04:00
/* Constructor for a conventional segment GDT (or LDT) entry */
/* This is a macro so it can be used in initializers */
# define GDT_ENTRY(flags, base, limit) \
( ( ( ( base ) & 0xff000000ULL ) < < ( 56 - 24 ) ) | \
( ( ( flags ) & 0x0000f0ffULL ) < < 40 ) | \
( ( ( limit ) & 0x000f0000ULL ) < < ( 48 - 16 ) ) | \
( ( ( base ) & 0x00ffffffULL ) < < 16 ) | \
( ( ( limit ) & 0x0000ffffULL ) ) )
2008-01-30 15:33:01 +03:00
/* Simple and small GDT entries for booting only */
# define GDT_ENTRY_BOOT_CS 2
# define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
# define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
# define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
2008-01-30 15:33:02 +03:00
# define GDT_ENTRY_BOOT_TSS (GDT_ENTRY_BOOT_CS + 2)
# define __BOOT_TSS (GDT_ENTRY_BOOT_TSS * 8)
2007-10-11 13:20:03 +04:00
# ifdef CONFIG_X86_32
2008-01-30 15:31:09 +03:00
/*
* The layout of the per - CPU GDT under Linux :
*
* 0 - null
* 1 - reserved
* 2 - reserved
* 3 - reserved
*
* 4 - unused < = = = = new cacheline
* 5 - unused
*
* - - - - - - - start of TLS ( Thread - Local Storage ) segments :
*
* 6 - TLS segment # 1 [ glibc ' s TLS segment ]
* 7 - TLS segment # 2 [ Wine ' s % fs Win32 segment ]
* 8 - TLS segment # 3
* 9 - reserved
* 10 - reserved
* 11 - reserved
*
* - - - - - - - start of kernel segments :
*
* 12 - kernel code segment < = = = = new cacheline
* 13 - kernel data segment
* 14 - default user CS
* 15 - default user DS
* 16 - TSS
* 17 - LDT
* 18 - PNPBIOS support ( 16 - > 32 gate )
* 19 - PNPBIOS support
* 20 - PNPBIOS support
* 21 - PNPBIOS support
* 22 - PNPBIOS support
* 23 - APM BIOS support
* 24 - APM BIOS support
* 25 - APM BIOS support
*
* 26 - ESPFIX small SS
* 27 - per - cpu [ offset to per - cpu data area ]
* 28 - unused
* 29 - unused
* 30 - unused
* 31 - TSS for double fault handler
*/
# define GDT_ENTRY_TLS_MIN 6
# define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
# define GDT_ENTRY_DEFAULT_USER_CS 14
# define GDT_ENTRY_DEFAULT_USER_DS 15
# define GDT_ENTRY_KERNEL_BASE 12
# define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0)
# define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1)
# define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE + 4)
# define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE + 5)
# define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
# define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)
# define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
# define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
# define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15)
# ifdef CONFIG_SMP
# define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
# else
# define __KERNEL_PERCPU 0
# endif
# define GDT_ENTRY_DOUBLEFAULT_TSS 31
/*
* The GDT has 32 entries
*/
# define GDT_ENTRIES 32
/* The PnP BIOS entries in the GDT */
# define GDT_ENTRY_PNPBIOS_CS32 (GDT_ENTRY_PNPBIOS_BASE + 0)
# define GDT_ENTRY_PNPBIOS_CS16 (GDT_ENTRY_PNPBIOS_BASE + 1)
# define GDT_ENTRY_PNPBIOS_DS (GDT_ENTRY_PNPBIOS_BASE + 2)
# define GDT_ENTRY_PNPBIOS_TS1 (GDT_ENTRY_PNPBIOS_BASE + 3)
# define GDT_ENTRY_PNPBIOS_TS2 (GDT_ENTRY_PNPBIOS_BASE + 4)
/* The PnP BIOS selectors */
# define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */
# define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */
# define PNP_DS (GDT_ENTRY_PNPBIOS_DS * 8) /* data segment for BIOS */
# define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */
# define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */
/* Bottom two bits of selector give the ring privilege level */
# define SEGMENT_RPL_MASK 0x3
/* Bit 2 is table indicator (LDT/GDT) */
# define SEGMENT_TI_MASK 0x4
/* User mode is privilege level 3 */
# define USER_RPL 0x3
/* LDT segment has TI set, GDT has it cleared */
# define SEGMENT_LDT 0x4
# define SEGMENT_GDT 0x0
/*
* Matching rules for certain types of segments .
*/
/* Matches only __KERNEL_CS, ignoring PnP / USER / APM segments */
# define SEGMENT_IS_KERNEL_CODE(x) (((x) & 0xfc) == GDT_ENTRY_KERNEL_CS * 8)
/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
# define SEGMENT_IS_FLAT_CODE(x) (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
# define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
2007-10-11 13:20:03 +04:00
# else
2008-01-30 15:31:09 +03:00
# include <asm/cache.h>
2008-05-29 03:19:53 +04:00
# define GDT_ENTRY_KERNEL32_CS 1
# define GDT_ENTRY_KERNEL_CS 2
# define GDT_ENTRY_KERNEL_DS 3
2008-01-30 15:31:09 +03:00
2008-05-29 03:19:53 +04:00
# define __KERNEL32_CS (GDT_ENTRY_KERNEL32_CS * 8)
2008-01-30 15:31:09 +03:00
/*
* we cannot use the same code segment descriptor for user and kernel
* - - not even in the long flat mode , because of different DPL / kkeil
* The segment offset needs to contain a RPL . Grr . - AK
* GDT layout to get 64 bit syscall right ( sysret hardcodes gdt offsets )
*/
2008-05-29 03:19:53 +04:00
# define GDT_ENTRY_DEFAULT_USER32_CS 4
# define GDT_ENTRY_DEFAULT_USER_DS 5
# define GDT_ENTRY_DEFAULT_USER_CS 6
# define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3)
2008-01-30 15:31:09 +03:00
# define __USER32_DS __USER_DS
# define GDT_ENTRY_TSS 8 /* needs two entries */
# define GDT_ENTRY_LDT 10 /* needs two entries */
# define GDT_ENTRY_TLS_MIN 12
# define GDT_ENTRY_TLS_MAX 14
# define GDT_ENTRY_PER_CPU 15 /* Abused to load per CPU data from limit */
# define __PER_CPU_SEG (GDT_ENTRY_PER_CPU * 8 + 3)
/* TLS indexes for 64bit - hardcoded in arch_prctl */
# define FS_TLS 0
# define GS_TLS 1
# define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
# define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
# define GDT_ENTRIES 16
2007-10-11 13:20:03 +04:00
# endif
2008-01-30 15:31:09 +03:00
2008-05-29 03:19:53 +04:00
# define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
# define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
# define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
# define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
2008-01-30 15:31:09 +03:00
# ifndef CONFIG_PARAVIRT
# define get_kernel_rpl() 0
# endif
2008-01-30 15:31:09 +03:00
/* User mode is privilege level 3 */
# define USER_RPL 0x3
/* LDT segment has TI set, GDT has it cleared */
# define SEGMENT_LDT 0x4
# define SEGMENT_GDT 0x0
/* Bottom two bits of selector give the ring privilege level */
# define SEGMENT_RPL_MASK 0x3
/* Bit 2 is table indicator (LDT/GDT) */
# define SEGMENT_TI_MASK 0x4
# define IDT_ENTRIES 256
2008-03-11 04:23:20 +03:00
# define NUM_EXCEPTION_VECTORS 32
2008-01-30 15:31:09 +03:00
# define GDT_SIZE (GDT_ENTRIES * 8)
# define GDT_ENTRY_TLS_ENTRIES 3
# define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
2008-01-30 15:33:06 +03:00
# ifdef __KERNEL__
# ifndef __ASSEMBLY__
2008-03-11 04:23:20 +03:00
extern const char early_idt_handlers [ NUM_EXCEPTION_VECTORS ] [ 10 ] ;
2008-01-30 15:33:06 +03:00
# endif
# endif
2008-01-30 15:31:09 +03:00
# endif