Disabling intrs + NMIs during CMOS access

This commit is contained in:
Thomas Oltmann 2025-05-14 20:09:52 +02:00
parent 9aba0ed6ec
commit d5555d273c
6 changed files with 54 additions and 8 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
config.mk
/tags
build/
drive.img
/compile_commands.json

View file

@ -10,6 +10,7 @@ CFLAGS += -ggdb
KERNEL_SOURCES_x86_64 := \
src/x86_64/apic.c \
src/x86_64/cmos.c \
src/x86_64/interrupt.S \
src/x86_64/loadcs.S \
src/x86_64/uart.c \
src/x86_64/mem.c \

View file

@ -11,7 +11,7 @@ LD = $(CROSS_PATH)/$(ARCH)-linux-ld
# Compilation flags
CFLAGS = -std=c17 -Wall -ffreestanding -nostdlib -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-80387
CPPFLAGS = -Iinclude
LDFLAGS = -nostdlib
LDFLAGS = -nostdlib -znoexecstack
BOOTBOOT = ../bootboot
MKBOOTIMG= $(BOOTBOOT)/mkbootimg/mkbootimg

View file

@ -0,0 +1,9 @@
#ifndef KARLOS_INTERRUPT_H
#define KARLOS_INTERRUPT_H
int int_enable(void);
int int_disable(void);
int int_save(void);
void int_restore(int state);
#endif

View file

@ -1,11 +1,15 @@
#include <sys/socket.h>
#include <stdbool.h>
#include <x86_64/asm.h>
#include <x86_64/interrupt.h>
#include <x86_64/cmos.h>
#define CMOS_SEL_PORT 0x70
#define CMOS_DATA_PORT 0x71
#define CMOS_NMI_DISABLE 0x80 // bit in sel port
#define CMOS_REG_SECONDS 0x00
#define CMOS_REG_MINUTES 0x02
#define CMOS_REG_HOURS 0x04
@ -49,14 +53,18 @@ bcd_to_binary(uint8_t bcd)
static void
cmos_access_rtc(struct datetime *dt)
{
while (cmos_read(CMOS_REG_STATA) & STATA_UPDATING) {}
int cpu_state = int_disable();
dt->seconds = cmos_read(CMOS_REG_SECONDS);
dt->minutes = cmos_read(CMOS_REG_MINUTES);
dt->hours = cmos_read(CMOS_REG_HOURS);
dt->day = cmos_read(CMOS_REG_DAY);
dt->month = cmos_read(CMOS_REG_MONTH);
while (cmos_read(CMOS_REG_STATA | CMOS_NMI_DISABLE) & STATA_UPDATING) {}
dt->seconds = cmos_read(CMOS_REG_SECONDS | CMOS_NMI_DISABLE);
dt->minutes = cmos_read(CMOS_REG_MINUTES | CMOS_NMI_DISABLE);
dt->hours = cmos_read(CMOS_REG_HOURS | CMOS_NMI_DISABLE);
dt->day = cmos_read(CMOS_REG_DAY | CMOS_NMI_DISABLE);
dt->month = cmos_read(CMOS_REG_MONTH | CMOS_NMI_DISABLE);
dt->year = cmos_read(CMOS_REG_YEAR);
int_restore(cpu_state);
}
void
@ -73,7 +81,10 @@ cmos_current_datetime(struct datetime *dt)
dt1.month != dt2.month ||
dt1.year != dt2.year);
uint8_t statb = cmos_read(CMOS_REG_STATB);
int cpu_state = int_disable();
uint8_t statb = cmos_read(CMOS_REG_STATB | CMOS_NMI_DISABLE);
cmos_read(0);
int_restore(cpu_state);
bool pm = false;
if (!(statb & STATB_24HOUR)) {

24
src/x86_64/interrupt.S Normal file
View file

@ -0,0 +1,24 @@
.global int_enable
.global int_disable
.global int_save
.global int_restore
.text
int_enable: pushfq
pop %rax
sti
ret
int_disable:pushfq
pop %rax
cli
ret
int_save: pushfq
pop %rax
ret
int_restore:push %rdi
popfq
ret