forked from lolo859/vystem
127 lines
3.9 KiB
C
127 lines
3.9 KiB
C
// SPDX-License-Identifier: MPL-2.0
|
|
#ifndef SH_LIB_GDT_H
|
|
#define SH_LIB_GDT_H
|
|
#include "std/status.h"
|
|
#include "std/type.h"
|
|
#include "irq/tss.h"
|
|
// Long mode GDT part
|
|
// GDT entry 64 bits structure
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_uint16 limit_low;
|
|
sh_uint16 base_low;
|
|
sh_uint8 base_mid;
|
|
sh_uint8 access;
|
|
sh_uint8 flags_limit_high;
|
|
sh_uint8 base_high;
|
|
} sh_gdt_GDT_ENTRY_64;
|
|
#pragma pack()
|
|
// GDT entry 128 bits (special TSS) structure
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_uint16 limit_low;
|
|
sh_uint16 base_low;
|
|
sh_uint8 base_mid;
|
|
sh_uint8 access;
|
|
sh_uint8 flags_limit_high;
|
|
sh_uint8 base_high;
|
|
sh_uint32 base_upper;
|
|
sh_uint32 reserved;
|
|
} sh_gdt_GDT_ENTRY_128;
|
|
#pragma pack()
|
|
// GDTR structure
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_uint16 limit;
|
|
sh_uint64 base;
|
|
} sh_gdt_GDTR;
|
|
#pragma pack()
|
|
// GDT structure for bootstrap core
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_gdt_GDT_ENTRY_64 null;
|
|
sh_gdt_GDT_ENTRY_64 kernel_code;
|
|
sh_gdt_GDT_ENTRY_64 kernel_data;
|
|
sh_gdt_GDT_ENTRY_64 user_code;
|
|
sh_gdt_GDT_ENTRY_64 user_data;
|
|
sh_gdt_GDT_ENTRY_128 tss;
|
|
} sh_gdt_GDT;
|
|
#pragma pack()
|
|
// GDT structure for all APs
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_gdt_GDT_ENTRY_64 null;
|
|
sh_gdt_GDT_ENTRY_64 kernel_code;
|
|
sh_gdt_GDT_ENTRY_64 kernel_data;
|
|
sh_gdt_GDT_ENTRY_64 user_code;
|
|
sh_gdt_GDT_ENTRY_64 user_data;
|
|
sh_gdt_GDT_ENTRY_128 tss[256];
|
|
} sh_gdt_GDT_AP;
|
|
#pragma pack()
|
|
// Generate access byte
|
|
inline sh_uint8 sh_gdt_fill_access_byte(sh_bool present,sh_uint8 dpl,sh_bool descriptor_type,sh_uint8 segment_type) {
|
|
return ((present?1:0)<<7)|((dpl&0x3)<<5)|((descriptor_type?1:0)<<4)|(segment_type&0xF);
|
|
}
|
|
// Generate flags byte (put all 4 bits in bit 0-3 of the returned byte)
|
|
inline sh_uint8 sh_gdt_fill_flags_byte(sh_bool g,sh_bool db,sh_bool l,sh_bool avl) {
|
|
return ((g?1:0)<<3)|((db?1:0)<<2)|((l?1:0)<<1)|((avl?1:0)<<0);
|
|
}
|
|
// Fill GDT entry 64 bits, expect flags as sh_gdt_fill_flags_byte would return it
|
|
sh_gdt_GDT_ENTRY_64 sh_gdt_fill_gdt_entry_64(sh_uint32 limit,sh_uint32 base,sh_uint8 access,sh_uint8 flags);
|
|
// Fill GDT entry 128 bits, expect flags as sh_gdt_fill_flags_byte would return it
|
|
sh_gdt_GDT_ENTRY_128 sh_gdt_fill_gdt_entry_128(sh_uint32 limit,sh_uint64 base,sh_uint8 access,sh_uint8 flags);
|
|
// Fill GDT with provided TSS
|
|
SH_STATUS sh_gdt_fill_gdt(sh_tss_TSS *tss,sh_gdt_GDT *gdt);
|
|
// Fill APs common GDT with provided TSS array
|
|
SH_STATUS sh_gdt_fill_gdt_ap(sh_tss_TSS *tss,sh_uint64 tss_count,sh_gdt_GDT_AP *gdt);
|
|
// Generate GDTR for AP GDT
|
|
sh_gdt_GDTR sh_gdt_make_gdtr_ap(sh_gdt_GDT_AP *gdt);
|
|
// Fill and load GDTR
|
|
SH_STATUS sh_gdt_load_gdtr(sh_gdt_GDT *gdt);
|
|
// Reload registers
|
|
SH_STATUS sh_gdt_reload_registers();
|
|
// 16/32 bits mode GDT part
|
|
// GDT entry 32 bits structure
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_uint16 limit_low;
|
|
sh_uint16 base_low;
|
|
sh_uint8 base_middle;
|
|
sh_uint8 access;
|
|
sh_uint8 granularity;
|
|
sh_uint8 base_high;
|
|
} sh_gdt_GDT_ENTRY_32;
|
|
#pragma pack()
|
|
// GDT 32 bits structure
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
sh_gdt_GDT_ENTRY_32 null;
|
|
sh_gdt_GDT_ENTRY_32 code_64;
|
|
sh_gdt_GDT_ENTRY_32 code;
|
|
sh_gdt_GDT_ENTRY_32 data;
|
|
} sh_gdt_GDT_32;
|
|
#pragma pack()
|
|
// Generate access byte
|
|
inline sh_uint8 sh_gdt_fill_access_byte_32(sh_bool present,sh_uint8 dpl,sh_bool descriptor_type,sh_uint8 segment_type) {
|
|
sh_uint8 access=0;
|
|
access|=(present?1:0)<<7;
|
|
access|=(dpl&0x3)<<5;
|
|
access|=(descriptor_type?1:0)<<4;
|
|
access|=(segment_type&0xF);
|
|
return access;
|
|
}
|
|
// Generate granularity byte
|
|
inline sh_uint8 sh_gdt_fill_granularity_byte_32(sh_bool granularity,sh_bool db,sh_bool l,sh_bool avl) {
|
|
sh_uint8 g=0;
|
|
g|=(granularity?1:0)<<7;
|
|
g|=(db?1:0)<<6;
|
|
g|=(l?1:0)<<5;
|
|
g|=(avl?1:0)<<4;
|
|
return g;
|
|
}
|
|
// Fill GDT entry 32 bits, expect granularity as sh_gdt_fill_granularity_byte_32 would return it
|
|
sh_gdt_GDT_ENTRY_32 sh_gdt_fill_gdt_entry_32(sh_uint32 limit,sh_uint32 base,sh_uint8 access,sh_uint8 granularity);
|
|
// Fill GDT 32 bits
|
|
SH_STATUS sh_gdt_fill_gdt_32(sh_gdt_GDT_32 *gdt_32);
|
|
#endif
|