Find errors here (IDT is not working):
kernel.c: 
```c
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "string/string.h"
#include "bios.h"
#include "terminal/terminal.h"
#include "cpu_work/gdt.h"
#include "cpu_work/idt.h"
#include "memory/memory.h"

#include "kernel_utils.h"

static void enter_protected_mode(void)
{
	terminal_writestring("Going to Protected mode...\n");

	interrupts_disable();
	NMI_disable();

	// Enable A20 line
	asm volatile("inb $0x92, %%al\n"
				 "orb $0x02, %%al\n"
				 "outb %%al, $0x92\n"
				 :
				 :
				 : "al");

	// Set CR0 to enable protected mode
	asm volatile("movl %%cr0, %%eax\n"
				 "orl $0x1, %%eax\n"
				 "movl %%eax, %%cr0\n"
				 :
				 :
				 : "eax");

	/*asm volatile("mov $0x10, %%ax\n" // Сегмент данных Ring 0
				 "mov %%ax, %%ds\n"
				 "mov %%ax, %%es\n"
				 "mov %%ax, %%fs\n"
				 "mov %%ax, %%gs\n"
				 :
				 :
				 : "eax");*/

	// Far jump to flush the instruction pipeline and reload CS
	asm volatile("ljmp $0x08, $protected_mode_start\n");
}

uint32_t get_current_privilege_level()
{
	uint32_t cs;
	asm volatile("mov %%cs, %0" : "=r"(cs)); // Чтение регистра CS
	return cs & 0x3;                         // Младшие два бита содержат CPL
}

void user_space_test(void)
{
	uint32_t cpl = get_current_privilege_level();
	if (cpl == 3)
	{
		// Мы находимся в Ring 3
		terminal_printf("Ring 3\n");
	}
	else
	{
		// Мы находимся в ядре (Ring 0)
		terminal_printf("Ring 0\n");
	}
}

void switch_to_ring3(uint32_t user_stack, uint32_t user_code)
{
	// Подготавливаем данные для перехода на Ring 3
	asm volatile("mov $0x20, %%ax\n" // Сегмент данных Ring 3
				 "mov %%ax, %%ds\n"
				 "mov %%ax, %%es\n"
				 "mov %%ax, %%fs\n"
				 "mov %%ax, %%gs\n"

				 "pushl $0x23\n" // Сегмент данных Ring 3
				 "pushl %0\n"    // Стек Ring 3 (user_stack)
				 "pushfl\n"      // EFLAGS
				 "popl %%eax\n"
				 "or $0x200, %%eax\n" // Включаем бит IF (разрешение прерываний)
				 "pushl %%eax\n"

				 "pushl $0x1B\n" // Сегмент кода Ring 3
				 "pushl %1\n"    // Адрес начала кода пользователя (user_code)
				 "iret\n"
				 :
				 : "r"(user_stack), "r"(user_code)
				 : "eax");
}

extern uint8_t kernel_stack[4096];
uint8_t user_stack[4096];
void protected_mode_start(void)
{
	bool cpuid_present = false;

	idt_setup();
	interrupts_enable();
	NMI_enable();

	terminal_printf("Entered Protected mode.\n");

	terminal_printf("CPUID: ");
	cpuid_present = cpuid_available();
	if (cpuid_present)
		terminal_printf("Avaliable\n");
	else
		terminal_printf("Not avaliable\n");

	switch_to_ring3((uint32_t)&user_stack[4096], (uint32_t)&user_space_test);

	while (1)
		;
}

void kernel_main(void)
{
	terminal_initialize();
	terminal_printf("Terminal initialized.\n");

	gdt_setup();

	enter_protected_mode();
}
```

idt.h:
```c
#pragma once

typedef struct
{
	uint16_t size;
	uint32_t offset;
} __attribute__((packed)) idt_descriptor;

typedef struct
{
	uint16_t offset_low;
	uint16_t segment_selector;
	uint8_t : 8;
	union
	{
		struct
		{
			uint8_t gate_type : 4;
			uint8_t : 1;
			uint8_t dpl : 2;
			uint8_t present : 1;
		} bits;
		uint8_t value;
	} __attribute__((packed)) flags;
	uint16_t offset_high;
} __attribute__((packed)) idt_entry;

void idt_setup(void);

typedef struct
{
	uint32_t ds;                                     // Сегмент данных
	uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Регистры, сохранённые при прерывании
	uint32_t int_no, err_code;                       // Номер прерывания и код ошибки
	uint32_t eip, cs, eflags, useresp, ss;           // Сохранённое состояние стека
} registers_t;

typedef void (*idt_handler_ptr_t)(const registers_t*);
void idt_set_handler(uint8_t num, idt_handler_ptr_t);
void idt_set_gate(uint8_t num, uint32_t offset, uint16_t selector, uint8_t flags);
```

idt.c:
```c
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "kernel_utils.h"
#include "bios.h"
#include "memory/memory.h"
#include "terminal/terminal.h"
#include "idt.h"

idt_entry idt[256];
idt_descriptor idt_ptr;

void exception_handler(const registers_t* regs)
{
	outb(0x20, 0x20);
	const uint8_t ring = regs->cs & 0x3;
	switch (regs->int_no)
	{
		case 0x0:
			terminal_printf("Division by zero!\n");
			break;
		case 0xD:
			terminal_printf("General Protection Fault\n");
			break;
		default:
			terminal_printf("Unknown interupt!\n");
	}

	kernel_panic();
}

extern void isr_stub();
extern void isr_stub_kdb();
void idt_setup(void)
{
	memset(&idt, 0, sizeof(idt));
	idt_set_handler(0xD, &isr_stub);
	idt_set_handler(0x21, &isr_stub_kdb);

	idt_ptr.size = sizeof(idt) - 1;
	idt_ptr.offset = (uint32_t)&idt;

	asm volatile("lidt %0" : : "m"(idt_ptr));
}

void idt_set_gate(uint8_t num, uint32_t offset, uint16_t selector, uint8_t flags)
{
	idt[num].offset_low = offset & 0xFFFF;
	idt[num].offset_high = (offset >> 16) & 0xFFFF;
	idt[num].segment_selector = selector;
	idt[num].flags.value = flags;
}

void idt_set_handler(uint8_t num, idt_handler_ptr_t handler)
{
	uint32_t address = (uint32_t)handler;
	idt[num].offset_low = address & 0xFFFF;
	idt[num].offset_high = (address >> 16) & 0xFFFF;
	idt[num].segment_selector = (uint16_t)0x08;
	idt[num].flags.bits.gate_type = 0xE;
	idt[num].flags.bits.present = 1;
	idt[num].flags.bits.dpl = 0;
}
```

idt.S:
```asm
.global isr_stub
isr_stub_old:
    pusha
    pushl %ds
    pushl %es
    pushl %fs
    pushl %gs 

    movw $0x10, %ax 
    movw %ax, %ds 
    movw %ax, %es 
    movw %ax, %fs 
    movw %ax, %gs 

    subl $8, %esp
    call exception_handler 
    addl $8, %esp 

    popl %gs
    popl %fs
    popl %es
    popl %ds

    popa
    iret

isr_stub:
    pushal
    cld 
    call exception_handler
    popal
    iret

.global isr_stub_kdb
isr_stub_kdb:
    pushal
    cld
    call exception_handler
    popal
    iret
```