Improve arch and asm, add some i386 code (#94)

This commit is contained in:
Alex Kotov 2022-06-24 08:42:46 +03:00 committed by GitHub
parent f714df3ba8
commit db226e3387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 217 additions and 56 deletions

View File

@ -1,3 +1,7 @@
2022-06-24 Alex Kotov <kotovalexarian@gmail.com>
* configure.ac: Added packages "arch-*" and "asm"
2022-06-23 Alex Kotov <kotovalexarian@gmail.com>
* configure.ac: Added package "drivers"

View File

@ -42,10 +42,19 @@ if WITH_LIBC
libkernaux_la_LIBADD += libc/libc.la
endif
#######
# ARCH #
#######
if WITH_ARCH_I386
libkernaux_la_SOURCES += src/arch/i386.c
endif
#######
# ASM #
#######
if WITH_ASM
if ASM_I386
libkernaux_la_SOURCES += src/asm/i386.S
endif
@ -55,6 +64,7 @@ endif
if ASM_X86_64
libkernaux_la_SOURCES += src/asm/x86_64.S
endif
endif
####################
# Default packages #

View File

@ -157,6 +157,11 @@ stable options.
All packages are included by default. To exclude all packages except those
explicitly included, use `--without-all`.
* `--with[out]-arch-all` - all architectures
* `--with[out]-arch-i386` - architecture i386
* `--with[out]-arch-riscv64` - architecture riscv64
* `--with[out]-arch-x86-64` - architecture x86-64
* `--with[out]-asm` - kernel assembler helpers
* `--with[out]-cmdline` - command line parser
* `--with[out]-free-list` - free list memory allocator
* `--with[out]-io` - input/output

View File

@ -44,35 +44,40 @@ AC_CONFIG_FILES([
###############
dnl Features (enabled by default)
AC_ARG_ENABLE([debug], AS_HELP_STRING([--disable-debug], [disable debugging]))
AC_ARG_ENABLE([float], AS_HELP_STRING([--disable-float], [disable floating-point arithmetic]))
AC_ARG_ENABLE([werror], AS_HELP_STRING([--disable-werror], [disable -Werror]))
AC_ARG_ENABLE([debug], AS_HELP_STRING([--disable-debug], [disable debugging]))
AC_ARG_ENABLE([float], AS_HELP_STRING([--disable-float], [disable floating-point arithmetic]))
AC_ARG_ENABLE([werror], AS_HELP_STRING([--disable-werror], [disable -Werror]))
dnl Features (disabled by default)
AC_ARG_ENABLE([freestanding], AS_HELP_STRING([--enable-freestanding], [build for freestanding environment]))
AC_ARG_ENABLE([split-libc], AS_HELP_STRING([--enable-split-libc], [split off libc]))
AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [enable usual tests and examples]))
AC_ARG_ENABLE([tests-all], AS_HELP_STRING([--enable-tests-all], [enable all tests]))
AC_ARG_ENABLE([tests-python], AS_HELP_STRING([--enable-tests-python], [enable tests that require Python 3 with YAML and Jinja2]))
AC_ARG_ENABLE([freestanding], AS_HELP_STRING([--enable-freestanding], [build for freestanding environment]))
AC_ARG_ENABLE([split-libc], AS_HELP_STRING([--enable-split-libc], [split off libc]))
AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [enable usual tests and examples]))
AC_ARG_ENABLE([tests-all], AS_HELP_STRING([--enable-tests-all], [enable all tests]))
AC_ARG_ENABLE([tests-python], AS_HELP_STRING([--enable-tests-python], [enable tests that require Python 3 with YAML and Jinja2]))
dnl Packages (enabled by default)
AC_ARG_WITH( [all], AS_HELP_STRING([--without-all], [without all default packages]))
AC_ARG_WITH( [cmdline], AS_HELP_STRING([--without-cmdline], [without command line parser]))
AC_ARG_WITH( [elf], AS_HELP_STRING([--without-elf], [without ELF utils]))
AC_ARG_WITH( [free-list], AS_HELP_STRING([--without-free-list], [without free list memory allocator]))
AC_ARG_WITH( [io], AS_HELP_STRING([--without-io], [without input/output]))
AC_ARG_WITH( [mbr], AS_HELP_STRING([--without-mbr], [without Master Boot Record]))
AC_ARG_WITH( [memmap], AS_HELP_STRING([--without-memmap], [without memory map]))
AC_ARG_WITH( [multiboot2], AS_HELP_STRING([--without-multiboot2], [without Multiboot 2 information parser]))
AC_ARG_WITH( [ntoa], AS_HELP_STRING([--without-ntoa], [without itoa/ftoa]))
AC_ARG_WITH( [pfa], AS_HELP_STRING([--without-pfa], [without Page Frame Allocator]))
AC_ARG_WITH( [printf], AS_HELP_STRING([--without-printf], [without printf]))
AC_ARG_WITH( [printf-fmt], AS_HELP_STRING([--without-printf-fmt], [without printf format parser]))
AC_ARG_WITH( [units], AS_HELP_STRING([--without-units], [without measurement units utils]))
AC_ARG_WITH( [all], AS_HELP_STRING([--without-all], [without all default packages]))
AC_ARG_WITH( [arch-all], AS_HELP_STRING([--without-arch-all], [without all architectures]))
AC_ARG_WITH( [arch-i386], AS_HELP_STRING([--without-arch-i386], [without architecture i386]))
AC_ARG_WITH( [arch-riscv64], AS_HELP_STRING([--without-arch-riscv64], [without architecture riscv64]))
AC_ARG_WITH( [arch-x86-64], AS_HELP_STRING([--without-arch-x86-64], [without architecture x86-64]))
AC_ARG_WITH( [asm], AS_HELP_STRING([--without-asm], [without kernel assembler helpers]))
AC_ARG_WITH( [cmdline], AS_HELP_STRING([--without-cmdline], [without command line parser]))
AC_ARG_WITH( [elf], AS_HELP_STRING([--without-elf], [without ELF utils]))
AC_ARG_WITH( [free-list], AS_HELP_STRING([--without-free-list], [without free list memory allocator]))
AC_ARG_WITH( [io], AS_HELP_STRING([--without-io], [without input/output]))
AC_ARG_WITH( [mbr], AS_HELP_STRING([--without-mbr], [without Master Boot Record]))
AC_ARG_WITH( [memmap], AS_HELP_STRING([--without-memmap], [without memory map]))
AC_ARG_WITH( [multiboot2], AS_HELP_STRING([--without-multiboot2], [without Multiboot 2 information parser]))
AC_ARG_WITH( [ntoa], AS_HELP_STRING([--without-ntoa], [without itoa/ftoa]))
AC_ARG_WITH( [pfa], AS_HELP_STRING([--without-pfa], [without Page Frame Allocator]))
AC_ARG_WITH( [printf], AS_HELP_STRING([--without-printf], [without printf]))
AC_ARG_WITH( [printf-fmt], AS_HELP_STRING([--without-printf-fmt], [without printf format parser]))
AC_ARG_WITH( [units], AS_HELP_STRING([--without-units], [without measurement units utils]))
dnl Packages (disabled by default)
AC_ARG_WITH( [drivers], AS_HELP_STRING([--with-drivers], [with drivers]))
AC_ARG_WITH( [libc], AS_HELP_STRING([--with-libc], [with libc replacement]))
AC_ARG_WITH( [drivers], AS_HELP_STRING([--with-drivers], [with drivers]))
AC_ARG_WITH( [libc], AS_HELP_STRING([--with-libc], [with libc replacement]))
@ -87,20 +92,32 @@ if test -z "$enable_tests_python"; then enable_tests_python=yes; fi
])
AS_IF([test "$enable_tests_all" = yes], do_enable_tests_all)
AC_DEFUN([do_without_arch_all],
[
if test -z "$with_arch_i386"; then with_arch_i386=no; fi
if test -z "$with_arch_riscv64"; then with_arch_riscv64=no; fi
if test -z "$with_arch_x86_64"; then with_arch_x86_64=no; fi
])
AS_IF([test "$with_arch_all" = no], do_without_arch_all)
AC_DEFUN([do_without_all],
[
if test -z "$with_cmdline"; then with_cmdline=no; fi
if test -z "$with_elf"; then with_elf=no; fi
if test -z "$with_free_list"; then with_free_list=no; fi
if test -z "$with_io"; then with_io=no; fi
if test -z "$with_mbr"; then with_mbr=no; fi
if test -z "$with_memmap"; then with_memmap=no; fi
if test -z "$with_multiboot2"; then with_multiboot2=no; fi
if test -z "$with_ntoa"; then with_ntoa=no; fi
if test -z "$with_pfa"; then with_pfa=no; fi
if test -z "$with_printf"; then with_printf=no; fi
if test -z "$with_printf_fmt"; then with_printf_fmt=no; fi
if test -z "$with_units"; then with_units=no; fi
if test -z "$with_arch_i386"; then with_arch_i386=no; fi
if test -z "$with_arch_riscv64"; then with_arch_riscv64=no; fi
if test -z "$with_arch_x86_64"; then with_arch_x86_64=no; fi
if test -z "$with_asm"; then with_asm=no; fi
if test -z "$with_cmdline"; then with_cmdline=no; fi
if test -z "$with_elf"; then with_elf=no; fi
if test -z "$with_free_list"; then with_free_list=no; fi
if test -z "$with_io"; then with_io=no; fi
if test -z "$with_mbr"; then with_mbr=no; fi
if test -z "$with_memmap"; then with_memmap=no; fi
if test -z "$with_multiboot2"; then with_multiboot2=no; fi
if test -z "$with_ntoa"; then with_ntoa=no; fi
if test -z "$with_pfa"; then with_pfa=no; fi
if test -z "$with_printf"; then with_printf=no; fi
if test -z "$with_printf_fmt"; then with_printf_fmt=no; fi
if test -z "$with_units"; then with_units=no; fi
])
AS_IF([test "$with_all" = no], do_without_all)
@ -124,6 +141,11 @@ AS_IF([test "$enable_tests_python" = yes], [enable_tests_python=yes], [enable_te
dnl Packages (enabled by default)
AS_IF([test "$with_all" = no ], [with_all=no], [with_all=yes])
AS_IF([test "$with_arch_all" = no ], [with_arch_all=no], [with_arch_all=yes])
AS_IF([test "$with_arch_i386" = no ], [with_arch_i386=no], [with_arch_i386=yes])
AS_IF([test "$with_arch_riscv64" = no ], [with_arch_riscv64=no], [with_arch_riscv64=yes])
AS_IF([test "$with_arch_x86_64" = no ], [with_arch_x86_64=no], [with_arch_x86_64=yes])
AS_IF([test "$with_asm" = no ], [with_asm=no], [with_asm=yes])
AS_IF([test "$with_cmdline" = no ], [with_cmdline=no], [with_cmdline=yes])
AS_IF([test "$with_elf" = no ], [with_elf=no], [with_elf=yes])
AS_IF([test "$with_free_list" = no ], [with_free_list=no], [with_free_list=yes])
@ -179,6 +201,10 @@ AM_CONDITIONAL([ENABLE_TESTS], [test "$enable_tests" = yes])
AM_CONDITIONAL([ENABLE_TESTS_PYTHON], [test "$enable_tests_python" = yes])
dnl Packages (enabled by default)
AM_CONDITIONAL([WITH_ARCH_I386], [test "$with_arch_i386" = yes])
AM_CONDITIONAL([WITH_ARCH_RISCV64], [test "$with_arch_riscv64" = yes])
AM_CONDITIONAL([WITH_ARCH_X86_64], [test "$with_arch_x86_64" = yes])
AM_CONDITIONAL([WITH_ASM], [test "$with_asm" = yes])
AM_CONDITIONAL([WITH_CMDLINE], [test "$with_cmdline" = yes])
AM_CONDITIONAL([WITH_ELF], [test "$with_elf" = yes])
AM_CONDITIONAL([WITH_FREE_LIST], [test "$with_free_list" = yes])
@ -219,6 +245,10 @@ AS_IF([test "$enable_tests" = yes], [AC_DEFINE([ENABLE_TESTS], [1]
AS_IF([test "$enable_tests_python" = yes], [AC_DEFINE([ENABLE_TESTS_PYTHON], [1], [enabled tests that require Python 3 with YAML and Jinja2])])
dnl Packages (enabled by default)
AS_IF([test "$with_arch_i386" = yes], [AC_DEFINE([WITH_ARCH_I386], [1], [with architecture i386])])
AS_IF([test "$with_arch_riscv64" = yes], [AC_DEFINE([WITH_ARCH_RISCV64], [1], [with architecture riscv64])])
AS_IF([test "$with_arch_x86_64" = yes], [AC_DEFINE([WITH_ARCH_X86_64], [1], [with architecture x86_64])])
AS_IF([test "$with_asm" = yes], [AC_DEFINE([WITH_ASM], [1], [with kernel assembler helpers])])
AS_IF([test "$with_cmdline" = yes], [AC_DEFINE([WITH_CMDLINE], [1], [with command line parser])])
AS_IF([test "$with_elf" = yes], [AC_DEFINE([WITH_ELF], [1], [with ELF utils])])
AS_IF([test "$with_free_list" = yes], [AC_DEFINE([WITH_FREE_LIST], [1], [with free list memory allocator])])
@ -246,18 +276,21 @@ AS_IF([test "$enable_debug" = yes], [AC_DEFINE([KERNAUX_DEBUG], [1]
##########################
dnl Packages (enabled by default)
AS_IF([test "$with_cmdline" = no], [AC_SUBST([comment_line_cmdline], [//])])
AS_IF([test "$with_elf" = no], [AC_SUBST([comment_line_elf], [//])])
AS_IF([test "$with_free_list" = no], [AC_SUBST([comment_line_free_list], [//])])
AS_IF([test "$with_io" = no], [AC_SUBST([comment_line_io], [//])])
AS_IF([test "$with_mbr" = no], [AC_SUBST([comment_line_mbr], [//])])
AS_IF([test "$with_memmap" = no], [AC_SUBST([comment_line_memmap], [//])])
AS_IF([test "$with_multiboot2" = no], [AC_SUBST([comment_line_multiboot2], [//])])
AS_IF([test "$with_ntoa" = no], [AC_SUBST([comment_line_ntoa], [//])])
AS_IF([test "$with_pfa" = no], [AC_SUBST([comment_line_pfa], [//])])
AS_IF([test "$with_printf" = no], [AC_SUBST([comment_line_printf], [//])])
AS_IF([test "$with_printf_fmt" = no], [AC_SUBST([comment_line_printf_fmt], [//])])
AS_IF([test "$with_units" = no], [AC_SUBST([comment_line_units], [//])])
AS_IF([test "$with_arch_i386" = no], [AC_SUBST([comment_line_arch_i386], [//])])
AS_IF([test "$with_arch_riscv64" = no], [AC_SUBST([comment_line_arch_riscv64], [//])])
AS_IF([test "$with_arch_x86_64" = no], [AC_SUBST([comment_line_arch_x86_64], [//])])
AS_IF([test "$with_cmdline" = no], [AC_SUBST([comment_line_cmdline], [//])])
AS_IF([test "$with_elf" = no], [AC_SUBST([comment_line_elf], [//])])
AS_IF([test "$with_free_list" = no], [AC_SUBST([comment_line_free_list], [//])])
AS_IF([test "$with_io" = no], [AC_SUBST([comment_line_io], [//])])
AS_IF([test "$with_mbr" = no], [AC_SUBST([comment_line_mbr], [//])])
AS_IF([test "$with_memmap" = no], [AC_SUBST([comment_line_memmap], [//])])
AS_IF([test "$with_multiboot2" = no], [AC_SUBST([comment_line_multiboot2], [//])])
AS_IF([test "$with_ntoa" = no], [AC_SUBST([comment_line_ntoa], [//])])
AS_IF([test "$with_pfa" = no], [AC_SUBST([comment_line_pfa], [//])])
AS_IF([test "$with_printf" = no], [AC_SUBST([comment_line_printf], [//])])
AS_IF([test "$with_printf_fmt" = no], [AC_SUBST([comment_line_printf_fmt], [//])])
AS_IF([test "$with_units" = no], [AC_SUBST([comment_line_units], [//])])

View File

@ -4,19 +4,31 @@
nobase_include_HEADERS = \
kernaux.h \
kernaux/arch/i386.h \
kernaux/arch/riscv64.h \
kernaux/arch/x86_64.h \
kernaux/assert.h \
kernaux/macro.h \
kernaux/version.h \
kernaux/generic/malloc.h \
kernaux/generic/mutex.h
########
# ARCH #
########
if WITH_ARCH_I386
nobase_include_HEADERS += kernaux/arch/i386.h
endif
if WITH_ARCH_RISCV64
nobase_include_HEADERS += kernaux/arch/riscv64.h
endif
if WITH_ARCH_X86_64
nobase_include_HEADERS += kernaux/arch/x86_64.h
endif
#######
# ASM #
#######
if WITH_ASM
if ASM_I386
nobase_include_HEADERS += kernaux/asm/i386.h
endif
@ -26,6 +38,7 @@ endif
if ASM_X86_64
nobase_include_HEADERS += kernaux/asm/x86_64.h
endif
endif
####################
# Default packages #

View File

@ -10,6 +10,10 @@
#include <kernaux/generic/malloc.h>
#include <kernaux/generic/mutex.h>
@comment_line_arch_i386@#include <kernaux/arch/i386.h>
@comment_line_arch_riscv64@#include <kernaux/arch/riscv64.h>
@comment_line_arch_x86_64@#include <kernaux/arch/x86_64.h>
@comment_line_cmdline@#include <kernaux/cmdline.h>
@comment_line_elf@#include <kernaux/elf.h>
@comment_line_free_list@#include <kernaux/free_list.h>
@ -22,7 +26,3 @@
@comment_line_printf@#include <kernaux/printf.h>
@comment_line_printf_fmt@#include <kernaux/printf_fmt.h>
@comment_line_units@#include <kernaux/units.h>
#include <kernaux/arch/i386.h>
#include <kernaux/arch/riscv64.h>
#include <kernaux/arch/x86_64.h>

View File

@ -49,9 +49,9 @@ extern "C" {
#define KERNAUX_ARCH_I386_CR4_PGE ((uint32_t)0x00000080) // 7: Page Global Enabled
// TODO: bits 8-31
// Global descriptor table entry
// Global or local descriptor table entry
// TODO: validate this according to spec
struct KernAux_Arch_I386_GDTE {
struct KernAux_Arch_I386_DTE {
unsigned limit_low : 16;
unsigned base_low : 24;
unsigned accessed : 1;
@ -70,6 +70,57 @@ struct KernAux_Arch_I386_GDTE {
}
__attribute__((packed));
/**
* @brief Task state segment
* @see The manual, page 132, figure 7-1
*/
struct KernAux_Arch_I386_TSS {
// 0x00
unsigned prev_tss : 16;
unsigned _zero0 : 16;
// 0x04
unsigned esp0 : 32;
unsigned ss0 : 16;
unsigned _zero1 : 16;
unsigned esp1 : 32;
unsigned ss1 : 16;
unsigned _zero2 : 16;
unsigned esp2 : 32;
unsigned ss2 : 16;
unsigned _zero3 : 16;
// 0x1c
unsigned cr3 : 32;
unsigned eip : 32;
unsigned eflags : 32;
unsigned eax : 32;
unsigned ecx : 32;
unsigned edx : 32;
unsigned ebx : 32;
unsigned esp : 32;
unsigned ebp : 32;
unsigned esi : 32;
unsigned edi : 32;
// 0x48
unsigned es : 16;
unsigned _zero4 : 16;
unsigned cs : 16;
unsigned _zero5 : 16;
unsigned ss : 16;
unsigned _zero6 : 16;
unsigned ds : 16;
unsigned _zero7 : 16;
unsigned fs : 16;
unsigned _zero8 : 16;
unsigned gs : 16;
unsigned _zero9 : 16;
unsigned ldt : 16;
unsigned _zero10 : 16;
// 0x64
unsigned _zero11 : 16;
unsigned io_map_base : 16;
}
__attribute__((packed));
// Page directory entry
// TODO: validate this according to spec
struct KernAux_Arch_I386_PDE {

View File

@ -15,6 +15,14 @@ inline static void kernaux_asm_i386_outportb(uint16_t port, uint8_t value);
inline static void kernaux_asm_i386_outportw(uint16_t port, uint16_t value);
inline static void kernaux_asm_i386_outportd(uint16_t port, uint32_t value);
void kernaux_asm_i386_flush_gdt(
volatile uint32_t pointer,
volatile uint32_t data_selector,
volatile uint32_t code_selector
);
void kernaux_asm_i386_flush_idt(volatile uint32_t pointer);
void kernaux_asm_i386_flush_tss(volatile uint16_t selector);
uint32_t kernaux_asm_i386_read_cr0();
uint32_t kernaux_asm_i386_read_cr4();

9
src/arch/i386.c Normal file
View File

@ -0,0 +1,9 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/arch/i386.h>
__attribute__((unused))
static const int
TSS_validation[sizeof(struct KernAux_Arch_I386_TSS) == 104 ? 1 : -1];

View File

@ -2,12 +2,40 @@
#include "config.h"
#endif
.global kernaux_asm_i386_flush_gdt
.global kernaux_asm_i386_flush_idt
.global kernaux_asm_i386_flush_tss
.global kernaux_asm_i386_read_cr0
.global kernaux_asm_i386_read_cr4
.global kernaux_asm_i386_write_cr0
.global kernaux_asm_i386_write_cr3
.global kernaux_asm_i386_write_cr4
kernaux_asm_i386_flush_gdt:
mov 4(%esp), %eax
mov 8(%esp), %edx
lgdt (%eax)
mov %edx, %ds
mov %edx, %es
mov %edx, %fs
mov %edx, %gs
mov %edx, %ss
pushl 12(%esp)
push $.flush
ljmp *(%esp)
.flush:
ret
kernaux_asm_i386_flush_idt:
mov 4(%esp), %eax
lidt (%eax)
ret
kernaux_asm_i386_flush_tss:
mov 4(%esp), %ax
ltr %ax
ret
kernaux_asm_i386_read_cr0:
mov %cr0, %eax
ret