Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _ASM_X86_SEGMENT_H
  2. #define _ASM_X86_SEGMENT_H
  3.  
  4. #include <linux/const.h>
  5.  
  6. /* Constructor for a conventional segment GDT (or LDT) entry */
  7. /* This is a macro so it can be used in initializers */
  8. #define GDT_ENTRY(flags, base, limit)                   \
  9.         ((((base)  & _AC(0xff000000,ULL)) << (56-24)) | \
  10.          (((flags) & _AC(0x0000f0ff,ULL)) << 40) |      \
  11.          (((limit) & _AC(0x000f0000,ULL)) << (48-16)) | \
  12.          (((base)  & _AC(0x00ffffff,ULL)) << 16) |      \
  13.          (((limit) & _AC(0x0000ffff,ULL))))
  14.  
  15. /* Simple and small GDT entries for booting only */
  16.  
  17. #define GDT_ENTRY_BOOT_CS       2
  18. #define __BOOT_CS               (GDT_ENTRY_BOOT_CS * 8)
  19.  
  20. #define GDT_ENTRY_BOOT_DS       (GDT_ENTRY_BOOT_CS + 1)
  21. #define __BOOT_DS               (GDT_ENTRY_BOOT_DS * 8)
  22.  
  23. #define GDT_ENTRY_BOOT_TSS      (GDT_ENTRY_BOOT_CS + 2)
  24. #define __BOOT_TSS              (GDT_ENTRY_BOOT_TSS * 8)
  25.  
  26. #define SEGMENT_RPL_MASK        0x3 /*
  27.                                      * Bottom two bits of selector give the ring
  28.                                      * privilege level
  29.                                      */
  30. #define SEGMENT_TI_MASK         0x4 /* Bit 2 is table indicator (LDT/GDT) */
  31. #define USER_RPL                0x3 /* User mode is privilege level 3 */
  32. #define SEGMENT_LDT             0x4 /* LDT segment has TI set... */
  33. #define SEGMENT_GDT             0x0 /* ... GDT has it cleared */
  34.  
  35. #ifdef CONFIG_X86_32
  36. /*
  37.  * The layout of the per-CPU GDT under Linux:
  38.  *
  39.  *   0 - null
  40.  *   1 - reserved
  41.  *   2 - reserved
  42.  *   3 - reserved
  43.  *
  44.  *   4 - unused                 <==== new cacheline
  45.  *   5 - unused
  46.  *
  47.  *  ------- start of TLS (Thread-Local Storage) segments:
  48.  *
  49.  *   6 - TLS segment #1                 [ glibc's TLS segment ]
  50.  *   7 - TLS segment #2                 [ Wine's %fs Win32 segment ]
  51.  *   8 - TLS segment #3
  52.  *   9 - reserved
  53.  *  10 - reserved
  54.  *  11 - reserved
  55.  *
  56.  *  ------- start of kernel segments:
  57.  *
  58.  *  12 - kernel code segment            <==== new cacheline
  59.  *  13 - kernel data segment
  60.  *  14 - default user CS
  61.  *  15 - default user DS
  62.  *  16 - TSS
  63.  *  17 - LDT
  64.  *  18 - PNPBIOS support (16->32 gate)
  65.  *  19 - PNPBIOS support
  66.  *  20 - PNPBIOS support
  67.  *  21 - PNPBIOS support
  68.  *  22 - PNPBIOS support
  69.  *  23 - APM BIOS support
  70.  *  24 - APM BIOS support
  71.  *  25 - APM BIOS support
  72.  *
  73.  *  26 - ESPFIX small SS
  74.  *  27 - per-cpu                        [ offset to per-cpu data area ]
  75.  *  28 - stack_canary-20                [ for stack protector ]
  76.  *  29 - unused
  77.  *  30 - unused
  78.  *  31 - TSS for double fault handler
  79.  */
  80. #define GDT_ENTRY_TLS_MIN       6
  81. #define GDT_ENTRY_TLS_MAX       (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
  82.  
  83. #define GDT_ENTRY_DEFAULT_USER_CS       14
  84.  
  85. #define GDT_ENTRY_DEFAULT_USER_DS       15
  86.  
  87. #define GDT_ENTRY_KERNEL_BASE           (12)
  88.  
  89. #define GDT_ENTRY_KERNEL_CS             (GDT_ENTRY_KERNEL_BASE+0)
  90.  
  91. #define GDT_ENTRY_KERNEL_DS             (GDT_ENTRY_KERNEL_BASE+1)
  92.  
  93. #define GDT_ENTRY_TSS                   (GDT_ENTRY_KERNEL_BASE+4)
  94. #define GDT_ENTRY_LDT                   (GDT_ENTRY_KERNEL_BASE+5)
  95.  
  96. #define GDT_ENTRY_PNPBIOS_BASE          (GDT_ENTRY_KERNEL_BASE+6)
  97. #define GDT_ENTRY_APMBIOS_BASE          (GDT_ENTRY_KERNEL_BASE+11)
  98.  
  99. #define GDT_ENTRY_ESPFIX_SS             (GDT_ENTRY_KERNEL_BASE+14)
  100. #define __ESPFIX_SS                     (GDT_ENTRY_ESPFIX_SS*8)
  101.  
  102. #define GDT_ENTRY_PERCPU                (GDT_ENTRY_KERNEL_BASE+15)
  103. #ifdef CONFIG_SMP
  104. #define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
  105. #else
  106. #define __KERNEL_PERCPU 0
  107. #endif
  108.  
  109. #define GDT_ENTRY_STACK_CANARY          (GDT_ENTRY_KERNEL_BASE+16)
  110. #ifdef CONFIG_CC_STACKPROTECTOR
  111. #define __KERNEL_STACK_CANARY           (GDT_ENTRY_STACK_CANARY*8)
  112. #else
  113. #define __KERNEL_STACK_CANARY           0
  114. #endif
  115.  
  116. #define GDT_ENTRY_DOUBLEFAULT_TSS       31
  117.  
  118. /*
  119.  * The GDT has 32 entries
  120.  */
  121. #define GDT_ENTRIES 32
  122.  
  123. /* The PnP BIOS entries in the GDT */
  124. #define GDT_ENTRY_PNPBIOS_CS32          (GDT_ENTRY_PNPBIOS_BASE + 0)
  125. #define GDT_ENTRY_PNPBIOS_CS16          (GDT_ENTRY_PNPBIOS_BASE + 1)
  126. #define GDT_ENTRY_PNPBIOS_DS            (GDT_ENTRY_PNPBIOS_BASE + 2)
  127. #define GDT_ENTRY_PNPBIOS_TS1           (GDT_ENTRY_PNPBIOS_BASE + 3)
  128. #define GDT_ENTRY_PNPBIOS_TS2           (GDT_ENTRY_PNPBIOS_BASE + 4)
  129.  
  130. /* The PnP BIOS selectors */
  131. #define PNP_CS32   (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */
  132. #define PNP_CS16   (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */
  133. #define PNP_DS     (GDT_ENTRY_PNPBIOS_DS * 8)   /* data segment for BIOS */
  134. #define PNP_TS1    (GDT_ENTRY_PNPBIOS_TS1 * 8)  /* transfer data segment */
  135. #define PNP_TS2    (GDT_ENTRY_PNPBIOS_TS2 * 8)  /* another data segment */
  136.  
  137.  
  138. /*
  139.  * Matching rules for certain types of segments.
  140.  */
  141.  
  142. /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
  143. #define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
  144.  
  145.  
  146. #else
  147. #include <asm/cache.h>
  148.  
  149. #define GDT_ENTRY_KERNEL32_CS 1
  150. #define GDT_ENTRY_KERNEL_CS 2
  151. #define GDT_ENTRY_KERNEL_DS 3
  152.  
  153. #define __KERNEL32_CS   (GDT_ENTRY_KERNEL32_CS * 8)
  154.  
  155. /*
  156.  * we cannot use the same code segment descriptor for user and kernel
  157.  * -- not even in the long flat mode, because of different DPL /kkeil
  158.  * The segment offset needs to contain a RPL. Grr. -AK
  159.  * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets)
  160.  */
  161. #define GDT_ENTRY_DEFAULT_USER32_CS 4
  162. #define GDT_ENTRY_DEFAULT_USER_DS 5
  163. #define GDT_ENTRY_DEFAULT_USER_CS 6
  164. #define __USER32_CS   (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
  165. #define __USER32_DS     __USER_DS
  166.  
  167. #define GDT_ENTRY_TSS 8 /* needs two entries */
  168. #define GDT_ENTRY_LDT 10 /* needs two entries */
  169. #define GDT_ENTRY_TLS_MIN 12
  170. #define GDT_ENTRY_TLS_MAX 14
  171.  
  172. #define GDT_ENTRY_PER_CPU 15    /* Abused to load per CPU data from limit */
  173. #define __PER_CPU_SEG   (GDT_ENTRY_PER_CPU * 8 + 3)
  174.  
  175. /* TLS indexes for 64bit - hardcoded in arch_prctl */
  176. #define FS_TLS 0
  177. #define GS_TLS 1
  178.  
  179. #define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
  180. #define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
  181.  
  182. #define GDT_ENTRIES 16
  183.  
  184. #endif
  185.  
  186. #define __KERNEL_CS     (GDT_ENTRY_KERNEL_CS*8)
  187. #define __KERNEL_DS     (GDT_ENTRY_KERNEL_DS*8)
  188. #define __USER_DS       (GDT_ENTRY_DEFAULT_USER_DS*8+3)
  189. #define __USER_CS       (GDT_ENTRY_DEFAULT_USER_CS*8+3)
  190. #ifndef CONFIG_PARAVIRT
  191. #define get_kernel_rpl()  0
  192. #endif
  193.  
  194. #define IDT_ENTRIES 256
  195. #define NUM_EXCEPTION_VECTORS 32
  196. /* Bitmask of exception vectors which push an error code on the stack */
  197. #define EXCEPTION_ERRCODE_MASK  0x00027d00
  198. #define GDT_SIZE (GDT_ENTRIES * 8)
  199. #define GDT_ENTRY_TLS_ENTRIES 3
  200. #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
  201.  
  202. #ifdef __KERNEL__
  203. #ifndef __ASSEMBLY__
  204. extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
  205. #ifdef CONFIG_TRACING
  206. #define trace_early_idt_handlers early_idt_handlers
  207. #endif
  208.  
  209. /*
  210.  * Load a segment. Fall back on loading the zero
  211.  * segment if something goes wrong..
  212.  */
  213. #define loadsegment(seg, value)                                         \
  214. do {                                                                    \
  215.         unsigned short __val = (value);                                 \
  216.                                                                         \
  217.         asm volatile("                                          \n"     \
  218.                      "1:        movl %k0,%%" #seg "             \n"     \
  219.                                                                         \
  220.                      ".section .fixup,\"ax\"                    \n"     \
  221.                      "2:        xorl %k0,%k0                    \n"     \
  222.                      "          jmp 1b                          \n"     \
  223.                      ".previous                                 \n"     \
  224.                                                                         \
  225.                      _ASM_EXTABLE(1b, 2b)                               \
  226.                                                                         \
  227.                      : "+r" (__val) : : "memory");                      \
  228. } while (0)
  229.  
  230. /*
  231.  * Save a segment register away
  232.  */
  233. #define savesegment(seg, value)                         \
  234.         asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
  235.  
  236. /*
  237.  * x86_32 user gs accessors.
  238.  */
  239. #ifdef CONFIG_X86_32
  240. #ifdef CONFIG_X86_32_LAZY_GS
  241. #define get_user_gs(regs)       (u16)({unsigned long v; savesegment(gs, v); v;})
  242. #define set_user_gs(regs, v)    loadsegment(gs, (unsigned long)(v))
  243. #define task_user_gs(tsk)       ((tsk)->thread.gs)
  244. #define lazy_save_gs(v)         savesegment(gs, (v))
  245. #define lazy_load_gs(v)         loadsegment(gs, (v))
  246. #else   /* X86_32_LAZY_GS */
  247. #define get_user_gs(regs)       (u16)((regs)->gs)
  248. #define set_user_gs(regs, v)    do { (regs)->gs = (v); } while (0)
  249. #define task_user_gs(tsk)       (task_pt_regs(tsk)->gs)
  250. #define lazy_save_gs(v)         do { } while (0)
  251. #define lazy_load_gs(v)         do { } while (0)
  252. #endif  /* X86_32_LAZY_GS */
  253. #endif  /* X86_32 */
  254.  
  255. static inline unsigned long get_limit(unsigned long segment)
  256. {
  257.         unsigned long __limit;
  258.         asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
  259.         return __limit + 1;
  260. }
  261.  
  262. #endif /* !__ASSEMBLY__ */
  263. #endif /* __KERNEL__ */
  264.  
  265. #endif /* _ASM_X86_SEGMENT_H */
  266.