2002-07-25 00:59:25 +04:00
|
|
|
/*
|
2006-01-11 01:54:36 +03:00
|
|
|
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
|
|
|
* Distributed under the terms of the NewOS License.
|
|
|
|
*/
|
2002-07-25 00:59:25 +04:00
|
|
|
#ifndef _KERNEL_ARCH_x86_DESCRIPTORS_H
|
|
|
|
#define _KERNEL_ARCH_x86_DESCRIPTORS_H
|
|
|
|
|
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
#define KERNEL_CODE_SEG 0x8
|
|
|
|
#define KERNEL_DATA_SEG 0x10
|
2002-07-26 02:28:59 +04:00
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
#define USER_CODE_SEG 0x1b
|
|
|
|
#define USER_DATA_SEG 0x23
|
|
|
|
|
2006-01-11 01:54:36 +03:00
|
|
|
#define APM_CODE32_SEGMENT 0x28
|
|
|
|
#define APM_CODE16_SEGMENT 0x30
|
|
|
|
#define APM_DATA_SEGMENT 0x38
|
2003-01-06 11:02:44 +03:00
|
|
|
|
2006-01-28 21:11:20 +03:00
|
|
|
#define BIOS_DATA_SEGMENT 0x40
|
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
#ifndef _ASSEMBLER
|
|
|
|
// this file can also be included from assembler as well
|
|
|
|
// (and is in arch_interrupts.S)
|
|
|
|
|
2006-01-28 21:11:20 +03:00
|
|
|
#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9
|
2005-04-05 01:43:47 +04:00
|
|
|
#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus())
|
2003-01-06 11:02:44 +03:00
|
|
|
#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus())
|
2006-01-11 01:54:36 +03:00
|
|
|
#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus())
|
2003-01-06 11:02:44 +03:00
|
|
|
|
|
|
|
|
|
|
|
// defines entries in the GDT/LDT
|
|
|
|
|
|
|
|
typedef struct segment_descriptor {
|
|
|
|
uint16 limit_00_15; // bit 0 - 15
|
|
|
|
uint16 base_00_15; // 16 - 31
|
|
|
|
uint32 base_23_16 : 8; // 0 - 7
|
|
|
|
uint32 type : 4; // 8 - 11
|
|
|
|
uint32 desc_type : 1; // 12 (0 = system, 1 = code/data)
|
|
|
|
uint32 privilege_level : 2; // 13 - 14
|
|
|
|
uint32 present : 1; // 15
|
|
|
|
uint32 limit_19_16 : 4; // 16 - 19
|
|
|
|
uint32 available : 1; // 20
|
|
|
|
uint32 zero : 1; // 21
|
|
|
|
uint32 d_b : 1; // 22
|
|
|
|
uint32 granularity : 1; // 23
|
|
|
|
uint32 base_31_24 : 8; // 24 - 31
|
|
|
|
} segment_descriptor;
|
|
|
|
|
|
|
|
enum descriptor_privilege_levels {
|
|
|
|
DPL_KERNEL = 0,
|
|
|
|
DPL_USER = 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum descriptor_types {
|
|
|
|
// segment types
|
|
|
|
DT_CODE_EXECUTE_ONLY = 0x8,
|
|
|
|
DT_CODE_ACCESSED = 0x9,
|
|
|
|
DT_CODE_READABLE = 0xa,
|
|
|
|
DT_CODE_CONFORM = 0xc,
|
|
|
|
DT_DATA_READ_ONLY = 0x0,
|
|
|
|
DT_DATA_ACCESSED = 0x1,
|
|
|
|
DT_DATA_WRITEABLE = 0x2,
|
|
|
|
DT_DATA_EXPANSION_DOWN = 0x4,
|
|
|
|
|
|
|
|
DT_TSS = 9,
|
2004-12-14 04:46:46 +03:00
|
|
|
/* non busy, 32 bit */
|
2003-01-06 11:02:44 +03:00
|
|
|
|
|
|
|
// descriptor types
|
|
|
|
DT_SYSTEM_SEGMENT = 0,
|
|
|
|
DT_CODE_DATA_SEGMENT = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
clear_segment_descriptor(struct segment_descriptor *desc)
|
|
|
|
{
|
|
|
|
*(long long *)desc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
2004-10-20 04:33:06 +04:00
|
|
|
set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base)
|
2003-01-06 11:02:44 +03:00
|
|
|
{
|
2004-10-20 04:33:06 +04:00
|
|
|
desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long
|
|
|
|
desc->base_23_16 = ((addr_t)base >> 16) & 0xff;
|
|
|
|
desc->base_31_24 = ((addr_t)base >> 24) & 0xff;
|
2003-01-06 11:02:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
2004-10-20 04:33:06 +04:00
|
|
|
set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit,
|
2003-01-06 11:02:44 +03:00
|
|
|
uint8 type, uint8 privilegeLevel)
|
|
|
|
{
|
|
|
|
set_segment_descriptor_base(desc, base);
|
|
|
|
|
2005-04-04 18:34:18 +04:00
|
|
|
// limit is 20 bits long
|
|
|
|
if (limit & 0xfff00000) {
|
|
|
|
desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff;
|
|
|
|
desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf;
|
|
|
|
desc->granularity = 1; // 4 KB granularity
|
|
|
|
} else {
|
|
|
|
desc->limit_00_15 = (addr_t)limit & 0x0ffff;
|
|
|
|
desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf;
|
|
|
|
desc->granularity = 0; // 1 byte granularity
|
|
|
|
}
|
|
|
|
limit >>= 12;
|
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
|
|
|
|
desc->type = type;
|
|
|
|
desc->desc_type = DT_CODE_DATA_SEGMENT;
|
|
|
|
desc->privilege_level = privilegeLevel;
|
|
|
|
|
|
|
|
desc->present = 1;
|
|
|
|
desc->available = 0; // system available bit is currently not used
|
2003-01-07 12:17:31 +03:00
|
|
|
desc->d_b = 1; // 32-bit code
|
2003-01-06 11:02:44 +03:00
|
|
|
|
|
|
|
desc->zero = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
2004-10-20 04:33:06 +04:00
|
|
|
set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit)
|
2003-01-06 11:02:44 +03:00
|
|
|
{
|
|
|
|
// the TSS descriptor has a special layout different from the standard descriptor
|
|
|
|
set_segment_descriptor_base(desc, base);
|
|
|
|
|
2004-10-20 04:33:06 +04:00
|
|
|
desc->limit_00_15 = (addr_t)limit & 0x0ffff;
|
2003-01-06 11:02:44 +03:00
|
|
|
desc->limit_19_16 = 0;
|
|
|
|
|
|
|
|
desc->type = DT_TSS;
|
|
|
|
desc->desc_type = DT_SYSTEM_SEGMENT;
|
|
|
|
desc->privilege_level = DPL_KERNEL;
|
|
|
|
|
|
|
|
desc->present = 1;
|
2005-04-05 01:43:47 +04:00
|
|
|
desc->granularity = 0; // 1 Byte granularity
|
2003-01-06 11:02:44 +03:00
|
|
|
desc->available = 0; // system available bit is currently not used
|
|
|
|
desc->d_b = 0;
|
|
|
|
|
|
|
|
desc->zero = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _ASSEMBLER */
|
|
|
|
|
|
|
|
#endif /* _KERNEL_ARCH_x86_DESCRIPTORS_H */
|