Add missing comments.
This commit is contained in:
+150
-96
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
/// Macro that encapsulate asm and volatile directives.
|
||||
#define ASM(a) __asm__ __volatile__(a)
|
||||
|
||||
#define CR0_PE 0x00000001u ///< Protected mode Enable.
|
||||
#define CR0_MP 0x00000002u ///< "Math" Present (e.g. npx), wait for it.
|
||||
#define CR0_EM 0x00000004u ///< EMulate NPX, e.g. trap, don't execute code.
|
||||
@@ -37,218 +34,275 @@
|
||||
#define CR4_PVI 0x00000002u ///< Protected-mode Virtual Interrupts.
|
||||
#define CR4_VME 0x00000001u ///< Virtual-8086 Mode Extensions.
|
||||
|
||||
static inline uint16_t get_es(void)
|
||||
/// @brief Reads the Extra Segment (DS).
|
||||
/// @return the value we read.
|
||||
static inline uint16_t get_es()
|
||||
{
|
||||
uint16_t es;
|
||||
ASM("mov %%es, %0"
|
||||
: "=r"(es));
|
||||
__asm__ __volatile__("mov %%es, %0"
|
||||
: "=r"(es));
|
||||
return es;
|
||||
}
|
||||
|
||||
/// @brief Sets the Extra Segment (DS).
|
||||
/// @param es the value we set.
|
||||
static inline void set_es(uint16_t es)
|
||||
{
|
||||
ASM("mov %0, %%es"
|
||||
:
|
||||
: "r"(es));
|
||||
__asm__ __volatile__("mov %0, %%es"
|
||||
:
|
||||
: "r"(es));
|
||||
}
|
||||
|
||||
static inline uint16_t get_ds(void)
|
||||
/// @brief Reads the Data Segment (DS).
|
||||
/// @return the value we read.
|
||||
static inline uint16_t get_ds()
|
||||
{
|
||||
uint16_t ds;
|
||||
ASM("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
__asm__ __volatile__("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
return ds;
|
||||
}
|
||||
|
||||
/// @brief Sets the Data Segment (DS).
|
||||
/// @param ds the value we set.
|
||||
static inline void set_ds(uint16_t ds)
|
||||
{
|
||||
ASM("mov %0, %%ds"
|
||||
:
|
||||
: "r"(ds));
|
||||
__asm__ __volatile__("mov %0, %%ds"
|
||||
:
|
||||
: "r"(ds));
|
||||
}
|
||||
|
||||
static inline uint16_t get_fs(void)
|
||||
/// @brief Reads FS.
|
||||
/// @return the value we read.
|
||||
static inline uint16_t get_fs()
|
||||
{
|
||||
uint16_t fs;
|
||||
ASM("mov %%fs, %0"
|
||||
: "=r"(fs));
|
||||
__asm__ __volatile__("mov %%fs, %0"
|
||||
: "=r"(fs));
|
||||
return fs;
|
||||
}
|
||||
|
||||
/// @brief Sets FS.
|
||||
/// @param fs the value we set.
|
||||
static inline void set_fs(uint16_t fs)
|
||||
{
|
||||
ASM("mov %0, %%fs"
|
||||
:
|
||||
: "r"(fs));
|
||||
__asm__ __volatile__("mov %0, %%fs"
|
||||
:
|
||||
: "r"(fs));
|
||||
}
|
||||
|
||||
static inline uint16_t get_gs(void)
|
||||
/// @brief Reads GS.
|
||||
/// @return the value we read.
|
||||
static inline uint16_t get_gs()
|
||||
{
|
||||
uint16_t gs;
|
||||
ASM("mov %%gs, %0"
|
||||
: "=r"(gs));
|
||||
__asm__ __volatile__("mov %%gs, %0"
|
||||
: "=r"(gs));
|
||||
return gs;
|
||||
}
|
||||
|
||||
/// @brief Sets GS.
|
||||
/// @param gs the value we set.
|
||||
static inline void set_gs(uint16_t gs)
|
||||
{
|
||||
ASM("mov %0, %%gs"
|
||||
:
|
||||
: "r"(gs));
|
||||
__asm__ __volatile__("mov %0, %%gs"
|
||||
:
|
||||
: "r"(gs));
|
||||
}
|
||||
|
||||
static inline uint16_t get_ss(void)
|
||||
/// @brief Reads the Stack Segment (SS).
|
||||
/// @return the value we read.
|
||||
static inline uint16_t get_ss()
|
||||
{
|
||||
uint16_t ss;
|
||||
ASM("mov %%ss, %0"
|
||||
: "=r"(ss));
|
||||
__asm__ __volatile__("mov %%ss, %0"
|
||||
: "=r"(ss));
|
||||
return ss;
|
||||
}
|
||||
|
||||
/// @brief Sets the Stack Segment (SS).
|
||||
/// @param ss the value we set.
|
||||
static inline void set_ss(uint16_t ss)
|
||||
{
|
||||
ASM("mov %0, %%ss"
|
||||
:
|
||||
: "r"(ss));
|
||||
__asm__ __volatile__("mov %0, %%ss"
|
||||
:
|
||||
: "r"(ss));
|
||||
}
|
||||
|
||||
static inline uintptr_t get_cr0(void)
|
||||
/// @brief Reads the current cr0 value.
|
||||
/// @return the value we read.
|
||||
static inline uintptr_t get_cr0()
|
||||
{
|
||||
uintptr_t cr0;
|
||||
ASM("mov %%cr0, %0"
|
||||
: "=r"(cr0));
|
||||
__asm__ __volatile__("mov %%cr0, %0"
|
||||
: "=r"(cr0));
|
||||
return (cr0);
|
||||
}
|
||||
|
||||
/// @brief Sets the cr0 value.
|
||||
/// @param cr0 the value we want to set.
|
||||
static inline void set_cr0(uintptr_t cr0)
|
||||
{
|
||||
ASM("mov %0, %%cr0"
|
||||
:
|
||||
: "r"(cr0));
|
||||
__asm__ __volatile__("mov %0, %%cr0"
|
||||
:
|
||||
: "r"(cr0));
|
||||
}
|
||||
|
||||
static inline uintptr_t get_cr3(void)
|
||||
/// @brief Reads the current cr3 value.
|
||||
/// @return the value we read.
|
||||
static inline uintptr_t get_cr3()
|
||||
{
|
||||
uintptr_t cr3;
|
||||
ASM("mov %%cr3, %0"
|
||||
: "=r"(cr3));
|
||||
__asm__ __volatile__("mov %%cr3, %0"
|
||||
: "=r"(cr3));
|
||||
return (cr3);
|
||||
}
|
||||
|
||||
/// @brief Sets the cr3 value.
|
||||
/// @param cr3 the value we want to set.
|
||||
static inline void set_cr3(uintptr_t cr3)
|
||||
{
|
||||
ASM("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(cr3));
|
||||
__asm__ __volatile__("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(cr3));
|
||||
}
|
||||
|
||||
static inline uintptr_t get_cr4(void)
|
||||
/// @brief Reads the current cr4 value.
|
||||
/// @return the value we read.
|
||||
static inline uintptr_t get_cr4()
|
||||
{
|
||||
uintptr_t cr4;
|
||||
ASM("mov %%cr4, %0"
|
||||
: "=r"(cr4));
|
||||
__asm__ __volatile__("mov %%cr4, %0"
|
||||
: "=r"(cr4));
|
||||
return (cr4);
|
||||
}
|
||||
|
||||
/// @brief Sets the cr4 value.
|
||||
/// @param cr4 the value we want to set.
|
||||
static inline void set_cr4(uintptr_t cr4)
|
||||
{
|
||||
ASM("mov %0, %%cr4"
|
||||
:
|
||||
: "r"(cr4)
|
||||
: "memory");
|
||||
__asm__ __volatile__("mov %0, %%cr4"
|
||||
:
|
||||
: "r"(cr4)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline uintptr_t get_eflags(void)
|
||||
/// @brief Reads entire contents of the EFLAGS register.
|
||||
/// @return the content of EFLAGS.
|
||||
static inline uintptr_t get_eflags()
|
||||
{
|
||||
uintptr_t eflags;
|
||||
/* "=rm" is safe here, because "pop" adjusts the stack before
|
||||
* it evaluates its effective address -- this is part of the
|
||||
* documented behavior of the "pop" instruction.
|
||||
*/
|
||||
ASM("pushf ; pop %0"
|
||||
: "=rm"(eflags)
|
||||
: /* no input */
|
||||
: "memory");
|
||||
// "=rm" is safe here, because "pop" adjusts the stack before
|
||||
// it evaluates its effective address -- this is part of the
|
||||
// documented behavior of the "pop" instruction.
|
||||
__asm__ __volatile__("pushf; pop %0"
|
||||
: "=rm"(eflags)
|
||||
: // no input
|
||||
: "memory");
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline void clear_ts(void)
|
||||
/// @brief Clears the task-switched (TS) flag in the CR0 register.
|
||||
static inline void clear_ts()
|
||||
{
|
||||
ASM("clts");
|
||||
__asm__ __volatile__("clts");
|
||||
}
|
||||
|
||||
static inline unsigned short get_tr(void)
|
||||
/// @brief Reads the segment selector from the task register (TR).
|
||||
/// @return
|
||||
static inline unsigned short get_tr()
|
||||
{
|
||||
unsigned short seg;
|
||||
ASM("str %0"
|
||||
: "=rm"(seg));
|
||||
__asm__ __volatile__("str %0"
|
||||
: "=rm"(seg));
|
||||
return (seg);
|
||||
}
|
||||
|
||||
static inline void set_tr(unsigned int seg)
|
||||
/// @brief Loads the source operand into the segment selector field of the task register.
|
||||
/// @param seg the segment selector we want to set.
|
||||
static inline void set_tr(unsigned short seg)
|
||||
{
|
||||
ASM("ltr %0"
|
||||
:
|
||||
: "rm"((unsigned short)(seg)));
|
||||
__asm__ __volatile__("ltr %0"
|
||||
:
|
||||
: "rm"(seg));
|
||||
}
|
||||
|
||||
static inline unsigned short sldt(void)
|
||||
/// @brief Reads the segment selector from the local descriptor table register (LDTR).
|
||||
/// @return the segment selector.
|
||||
static inline unsigned short sldt()
|
||||
{
|
||||
unsigned short seg;
|
||||
ASM("sldt %0"
|
||||
: "=rm"(seg));
|
||||
__asm__ __volatile__("sldt %0"
|
||||
: "=rm"(seg));
|
||||
return (seg);
|
||||
}
|
||||
|
||||
static inline void lldt(unsigned int seg)
|
||||
/// @brief Loads the source operand into the segment selector field of the local descriptor table register (LDTR).
|
||||
/// @param seg The segment selector we need to set.
|
||||
static inline void lldt(unsigned short seg)
|
||||
{
|
||||
ASM("lldt %0"
|
||||
:
|
||||
: "rm"((unsigned short)(seg)));
|
||||
__asm__ __volatile__("lldt %0"
|
||||
:
|
||||
: "rm"(seg));
|
||||
}
|
||||
|
||||
/// @brief Loads the values in the source operand into the global descriptor
|
||||
/// table register (GDTR) or the interrupt descriptor table register (IDTR).
|
||||
/// @param desc the value we need to load.
|
||||
static inline void lgdt(uintptr_t *desc)
|
||||
{
|
||||
ASM("lgdt %0"
|
||||
:
|
||||
: "m"(*desc));
|
||||
__asm__ __volatile__("lgdt %0"
|
||||
:
|
||||
: "m"(*desc));
|
||||
}
|
||||
|
||||
/// @brief Loads the values in the source operand into the global descriptor
|
||||
/// table register (GDTR) or the interrupt descriptor table register (IDTR).
|
||||
/// @param desc the value we need to load.
|
||||
static inline void lidt(uintptr_t *desc)
|
||||
{
|
||||
ASM("lidt %0"
|
||||
:
|
||||
: "m"(*desc));
|
||||
__asm__ __volatile__("lidt %0"
|
||||
:
|
||||
: "m"(*desc));
|
||||
}
|
||||
|
||||
/// @brief Enable IRQs.
|
||||
/// @brief Set interrupt flag; external, maskable interrupts enabled at the end
|
||||
/// of the next instruction.
|
||||
static inline void sti()
|
||||
{
|
||||
ASM("sti" ::
|
||||
: "memory");
|
||||
__asm__ __volatile__("sti"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/// @brief Disable IRQs.
|
||||
/// @brief Clear interrupt flag; interrupts disabled when interrupt flag
|
||||
/// cleared.
|
||||
static inline void cli()
|
||||
{
|
||||
ASM("cli" ::
|
||||
: "memory");
|
||||
__asm__ __volatile__("cli"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void swapgs(void)
|
||||
/// @brief Exchanges the current GS base register value with the value contained
|
||||
/// in MSR address C0000102H.
|
||||
static inline void swapgs()
|
||||
{
|
||||
ASM("swapgs");
|
||||
__asm__ __volatile__("swapgs");
|
||||
}
|
||||
|
||||
static inline void hlt(void)
|
||||
/// @brief Halts the CPU until the next external interrupt is fired.
|
||||
static inline void hlt()
|
||||
{
|
||||
ASM("hlt");
|
||||
__asm__ __volatile__("hlt");
|
||||
}
|
||||
|
||||
/// @brief Pause.
|
||||
/// @brief Gives hint to processor that improves performance of spin-wait loops.
|
||||
static inline void pause()
|
||||
{
|
||||
ASM("pause");
|
||||
__asm__ __volatile__("pause");
|
||||
}
|
||||
|
||||
// == Memory clobbers =========================================================
|
||||
@@ -266,6 +320,6 @@ static inline void pause()
|
||||
// Making an inline asm block "volatile" as in this example, ensures that,
|
||||
// as it optimizes, the compiler does not move any instructions above or
|
||||
// below the block of asm statements.
|
||||
// ASM(" addic. %0,%1,%2\n" : "=r"(res): "=r"(a),"r"(a))
|
||||
// __asm__ __volatile__(" addic. %0,%1,%2\n" : "=r"(res): "=r"(a),"r"(a))
|
||||
// This can be particularly important in cases when the code is accessing
|
||||
// shared memory.
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/// @brief Prints the given message and then safely stop the execution of
|
||||
/// the kernel.
|
||||
/// @brief Prints the given message and safely stop the execution of the kernel.
|
||||
/// @param msg The message that has to be shown.
|
||||
void kernel_panic(const char *msg);
|
||||
|
||||
/// @brief Sends a kernel panic with the given message.
|
||||
#define TODO(msg) kernel_panic(#msg);
|
||||
|
||||
@@ -68,8 +68,8 @@ void paging_switch_directory_va(page_directory_t *dir)
|
||||
|
||||
void paging_flush_tlb_single(unsigned long addr)
|
||||
{
|
||||
ASM("invlpg (%0)" ::"r"(addr)
|
||||
: "memory");
|
||||
__asm__ __volatile__("invlpg (%0)" ::"r"(addr)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
uint32_t create_vm_area(mm_struct_t *mm,
|
||||
@@ -165,12 +165,12 @@ uint32_t clone_vm_area(mm_struct_t *mm, vm_area_struct_t *area, int cow, uint32_
|
||||
|
||||
static void __init_pagedir(page_directory_t *pdir)
|
||||
{
|
||||
*pdir = (page_directory_t){ {0} };
|
||||
*pdir = (page_directory_t){ { 0 } };
|
||||
}
|
||||
|
||||
static void __init_pagetable(page_table_t *ptable)
|
||||
{
|
||||
*ptable = (page_table_t){ {0} };
|
||||
*ptable = (page_table_t){ { 0 } };
|
||||
}
|
||||
|
||||
void paging_init(boot_info_t *info)
|
||||
|
||||
Reference in New Issue
Block a user