95 lines
3.4 KiB
C
95 lines
3.4 KiB
C
/*
|
|
Copyright 2022 Mattia Giambirtone & Contributors
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
#ifndef TSOS_CPU_IDT_H
|
|
#define TSOS_CPU_IDT_H
|
|
|
|
#include "kernel/types.h"
|
|
|
|
#define KERNEL_CODE_SEGMENT_SELECTOR 0x8
|
|
|
|
|
|
|
|
typedef struct {
|
|
/*
|
|
An entry in the Interrupt
|
|
Descriptor Table of the CPU
|
|
*/
|
|
|
|
u16 handlerOffsetLow; /* Low 16 bits of handler's address */
|
|
u16 segmentSelector; /* Kernel segment selector */
|
|
u8 _unused; /* This is always zero! (padding?) */
|
|
u8 flags; /* Flags of this handler */
|
|
u16 handlerOffsetHigh; /* High 16 bits of handler's address */
|
|
/*
|
|
The flags byte is structured as follows:
|
|
- Bit 7 : "Interrupt is present". Serves to make the whole structure valid
|
|
- Bits 6-5: Privilege level ("ring") of the caller. Ring zero is the kernel,
|
|
ring one is usually reserved for driver code, ring two is unused and ring 3
|
|
is userland code
|
|
- Bits 4-0: The gate's type and attributes. They are structured as follows:
|
|
- Bit 4 : Set to zero for interrupts and one for traps (traps are usually used for exceptions)
|
|
- Bit 3-0: The type of the gate (whether it's 16- or 32-bit, etc.)
|
|
The only valid values for bits 4-0 are five (taken from the OSDev wiki):
|
|
- 0b0101 or 0x5: Task Gate. Note that in this case, the offset value is unused and should be set to zero.
|
|
- 0b0110 or 0x6: 16-bit Interrupt Gate
|
|
- 0b0111 or 0x7: 16-bit Trap Gate
|
|
- 0b1110 or 0xE: 32-bit Interrupt Gate
|
|
- 0b1111 or 0xF: 32-bit Trap Gate
|
|
*/
|
|
} __attribute__((packed)) GateDescriptor;
|
|
// The packed attribute tells gcc not to align
|
|
// or reorder the struct's fields in memory.
|
|
// Doing so in normal code is fine and speeds up
|
|
// memory accessing, but the CPU expects the structure
|
|
// of a GDT entry to be exactly in this order, with no
|
|
// padding (besides, each entry is exactly 8 bytes long
|
|
// already, so the performance hit is probably neglibible)
|
|
|
|
|
|
typedef struct {
|
|
/*
|
|
The Interrupt Descriptor Table
|
|
Register. Stores the location
|
|
of the IDT in memory
|
|
*/
|
|
|
|
u16 size; /* Size of the IDT. Always one less than its true size*/
|
|
u32 loc;
|
|
} __attribute__((packed)) IDTRegister;
|
|
|
|
|
|
/*
|
|
Note: While the IDT can contain up to 2 ** 16 entries, only the first
|
|
256 are considered and the rest is ignored; However, if there's less than
|
|
256 entries in the table, when the CPU then tries to fetch an interrupt gate
|
|
and doesn't find one, a GP (General Protection) fault is triggered. This may
|
|
cause the CPU to triple fault if the GP handler itself hasn't been set, as it
|
|
is one of the interrupt handlers the CPU expects to be present
|
|
*/
|
|
|
|
|
|
#define IDT_SIZE 256
|
|
|
|
/* These are the IDT and IDTR (We'll access these from asm) */
|
|
GateDescriptor idt[IDT_SIZE];
|
|
IDTRegister idtReg;
|
|
|
|
/* Prototypes */
|
|
void setIDTGate(i32 n, u32 handler);
|
|
void setIDT(void);
|
|
|
|
#endif |