Compare commits

...

2 Commits

Author SHA1 Message Date
f5deb1048a Kernel: Add functions to push and pop the interrupt state
This can be useful when you want to disable interrupts, but then only enable them back if they were previously enabled.
2022-10-12 12:58:56 +02:00
b3e16068ef Kernel: Add Utilities::get_rflags(), and thus Interrupts::are_enabled() 2022-10-12 12:56:55 +02:00
5 changed files with 52 additions and 0 deletions

View File

@ -8,4 +8,10 @@ namespace Interrupts
bool is_in_handler(); bool is_in_handler();
void return_from_handler(Context* context); void return_from_handler(Context* context);
bool are_enabled();
bool were_enabled();
void push_and_disable();
void push_and_enable();
void pop();
} }

View File

@ -5,4 +5,6 @@ namespace Utilities
{ {
uint64_t get_blocks_from_size(uint64_t blocksize, uint64_t get_blocks_from_size(uint64_t blocksize,
uint64_t size); // Returns how many blocks of size blocksize does size occupy. uint64_t size); // Returns how many blocks of size blocksize does size occupy.
uint64_t get_rflags();
} }

View File

@ -1,4 +1,5 @@
#include "interrupts/Interrupts.h" #include "interrupts/Interrupts.h"
#include "misc/utils.h"
#include "trace/StackTracer.h" #include "trace/StackTracer.h"
void Interrupts::disable() void Interrupts::disable()
@ -25,3 +26,34 @@ void Interrupts::return_from_handler(Context* context)
: :
: "r"(context)); : "r"(context));
} }
bool Interrupts::are_enabled()
{
return (Utilities::get_rflags() & 0x200) > 0;
}
static bool saved_interrupt_state;
void Interrupts::push_and_disable()
{
saved_interrupt_state = are_enabled();
disable();
}
void Interrupts::push_and_enable()
{
saved_interrupt_state = are_enabled();
enable();
}
void Interrupts::pop()
{
if (saved_interrupt_state && !are_enabled()) enable();
else if (!saved_interrupt_state && are_enabled())
disable();
}
bool Interrupts::were_enabled()
{
return saved_interrupt_state;
}

View File

@ -26,3 +26,9 @@ asm_enable_sse:
or ax, 3 << 9 or ax, 3 << 9
mov cr4, rax mov cr4, rax
ret ret
global asm_get_rflags
asm_get_rflags:
pushfq
pop rax
ret

View File

@ -4,3 +4,9 @@ uint64_t Utilities::get_blocks_from_size(uint64_t blocksize, uint64_t size)
{ {
return (size + (blocksize - 1)) / blocksize; return (size + (blocksize - 1)) / blocksize;
} }
extern "C" uint64_t asm_get_rflags();
uint64_t Utilities::get_rflags()
{
return asm_get_rflags();
}