Skip to content

Commit

Permalink
Built SMP initialization code in a separate binary which will be incl…
Browse files Browse the repository at this point in the history
…uded in kernel and later copied at 0x7c00 address to execute. Turned on protected mode and paging for APs. Reserved stack space for APs. Using common file krnlconst.hdr to define constant for C and assembly that will be processed by command line scripts and will generate krnlconst.h and krnlconst.S - these two files will be included by source files.
  • Loading branch information
shoily committed Oct 11, 2020
1 parent 4c3f239 commit ad05c52
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 39 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
It supports boot loader, kernel with protected mode, paging, E820 enumeration, interrupt and exception handling, system calls, user mode, local APIC and multiprocessor.

<b>Instructions for building kernel -</b><br>
cat krnlconst.hdr | awk 'BEGIN{print "#ifndef _KERNEL_CONST_H"};{print "#define " $1 " " $2};END{print "#endif";}' > krnlconst.h<br>
cat krnlconst.hdr | awk '{print ".equ " $1 ", " $2};' > krnlconst.S<br>

as --32 mpinit.S -o mpinit.o<br>
ld -static -T mpinit.ld -m elf_i386 -nostdlib --nmagic -o mpinit.elf mpinit.o<br>
objcopy -O binary mpinit.elf mpinit.bin<br>

as --32 boot32.S -o boot32.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c util.c -o util.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c system.c -o system.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c apic.c -o apic.o<br>
as --32 handlr32.S -o handlr32.o<br>
as --32 mpinit.S -o mpinit.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c smp.c -o smp.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c setup32.c -o setup32.o<br>
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c start.c -o start.o<br>
Expand All @@ -17,7 +23,7 @@ gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nosta
gcc -m32 -std=gnu99 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -ffreestanding -fno-pic -Wall -Wextra -Werror -c usermode.c -o usermode.o<br>


ld -static -T kernel32.ld -m elf_i386 -nostdlib --nmagic boot32.o util.o system.o apic.o mpinit.o smp.o setup32.o handlr32.o memory.o page32.o usermode.o start.o -o xiskernel.elf<br>
ld -static -T kernel32.ld -m elf_i386 -nostdlib --nmagic boot32.o util.o system.o apic.o smp.o setup32.o handlr32.o memory.o page32.o usermode.o start.o -o xiskernel.elf<br>
objcopy -O binary xiskernel.elf xiskernel.bin<br>

<b>Instructions for building boot loader -</b><br>
Expand Down
13 changes: 13 additions & 0 deletions boot32.S
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,16 @@ highaddress:

loop:
jmp loop

.section mp_init, "ax"
.global init_ap
.align 8
init_ap:
.incbin "mpinit.bin"

.global init_ap_size
.align 8
.global init_ap_size

init_ap_size:
.int init_ap_size - init_ap
13 changes: 6 additions & 7 deletions bootldr.S
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
/* */
/*****************************************************************************/

.include "krnlsize.h"
.equ E820_MAP_ADDR, 0x1008
.equ PROTECTED_MODE_STACK, 0xf000
.include "krnlsize.S"
.include "krnlconst.S"
.equ KERNEL_SECTORS, ((KERNEL_SIZE + 0x200 -1) / 0x200)

// machine boots in 16bit real mode
Expand Down Expand Up @@ -45,7 +44,7 @@ _start:
xorl %ebx, %ebx
movl $24, %ecx
movl $0x534d4150, %edx
movl $E820_MAP_ADDR, %edi
movl $E820_MAP_ADDRESS, %edi
movl $1, 20(%edi)
int $0x15

Expand Down Expand Up @@ -90,7 +89,7 @@ e820_failed:
e820_done:

// store e820 count in memory
movl %ebp, E820_MAP_ADDR-4
movl %ebp, E820_MAP_COUNT

// write '8' in the screen to indicate e820 success
movb $'8', %al
Expand Down Expand Up @@ -174,7 +173,7 @@ a20_line:
cli

// jump to protected mode
ljmpl *segmentoffsetvalue
ljmpl *codesegaddr

lba_read_error:

Expand Down Expand Up @@ -264,7 +263,7 @@ gdtdescriptor:
.word end_of_gdt-gdt-1
.long gdt

segmentoffsetvalue:
codesegaddr:
.long protectedmodeaddress
.word code_seg

Expand Down
15 changes: 6 additions & 9 deletions kernel32.ld
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,18 @@ ENTRY(_start)
SECTIONS
{
. = 0x80100000;
.text : AT(ADDR(.text) - 0x80000000) {*(.text); }
.data : AT(ADDR(.data) - 0x80000000) {*(.data); }
.bss : AT(ADDR(.bss) - 0x80000000) {*(.bss); }
. = ALIGN(4096);
.um : AT(ADDR(.um) - 0x80000000) {*(.um);}
.text : {*(.text); }
.data : {*(.data); }
.bss : {*(.bss); }
um_size = SIZEOF(um);
. = ALIGN(4096);
.mp_init : AT(ADDR(.mp_init) - 0x80000000) {*(.mp_init);}
mp_init_size = SIZEOF(mp_init);
.kernel_data ALIGN(4096) : AT(ADDR(.kernel_data) - 0x80000000) {*(.kernel_data); }
. = ALIGN(8);
.mp_init : {*(.mp_init); }
. = ALIGN(4096);
_kernel_pg_dir = .;
_kernel_pg_table_0 = _kernel_pg_dir + 0x1000;
_kernel_stack_0 = _kernel_pg_table_0 + 0x1000;
_kernel_stack_0_start = _kernel_stack_0 + 0x2000;
_kernel_stack_ap_start = _kernel_stack_0_start + (0x2000 * 32);
_kernel_private_data = _kernel_stack_0_start + 8;
_kernel_heap_start = (_kernel_private_data + 0x1000) & ~(0xfff);
}
9 changes: 9 additions & 0 deletions krnlconst.hdr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
VIDEO_BUFFER 0xb8000
E820_MAP_ADDRESS 0x1008
E820_MAP_COUNT 0x1004
PROTECTED_MODE_STACK 0xf000
AP_FIRST_STACK 0xfff0
AP_LAPIC_BASE_REGISTER 0xfff4
AP_COUNT_PHYS_ADDR 0xfff8
AP_KERNEL_PG_DIR 0xfffc
KERNEL_VIRT_ADDR 0x80000000
98 changes: 91 additions & 7 deletions mpinit.S
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
/* */
/*****************************************************************************/

.equ AP_COUNT_PHYS_ADDR, 0xfff8
.code16

.globl init_ap
.include "krnlconst.S"

.section "mp_init", "ax"
.code16
.text

init_ap:
.globl _start
_start:

cli
xorw %ax, %ax
Expand All @@ -26,6 +25,91 @@ init_ap:
movw %ax, %fs
movw %ax, %gs

incw AP_COUNT_PHYS_ADDR
// loads gdt
xorw %ax, %ax
movw %ax, %ds
lgdt gdtdescriptor

// turn on protected mode
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0

cli

// jump to protected mode
ljmpl *codesegaddr

// protected mode code
.code32

protectedmodeaddress:

movl $data_seg, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss
movl %eax, %fs
movl %eax, %gs


// turning on paging
movl AP_KERNEL_PG_DIR, %eax
movl %eax, %cr3
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0

lock incw AP_COUNT_PHYS_ADDR+KERNEL_VIRT_ADDR

hlt

.code32
.section ".high", "ax"

highaddress:

// initialize protected mode stack
movl $PROTECTED_MODE_STACK, %eax
movl %eax, %esp
movl %eax, %ebp

hlt

.data
// global descriptor table (GDT)
.p2align 5
gdt:
// offset 0x0 - NULL descriptor
.quad 0

code_seg_addr:
// offset 0x8 - cs should point to this descriptor
.word 0xFFFF
.word 0
.byte 0
.byte 0x9A
.byte 0xCF
.byte 0

data_seg_addr:
// offset 0x10 - ds, ss, es, fs, and gs should point to this descriptor
.word 0xFFFF
.word 0
.byte 0
.byte 0x92
.byte 0xCF
.byte 0

end_of_gdt:

codesegaddr:
.long protectedmodeaddress
.word code_seg

gdtdescriptor:
.word end_of_gdt-gdt-1
.long gdt

.equ code_seg, code_seg_addr-gdt
.equ data_seg, data_seg_addr-gdt
5 changes: 3 additions & 2 deletions setup32.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
#ifndef _SETUP_32_H
#define _SETUP_32_H

#define NUM_SMPS 32

#define USER_CODE_SEG 0x10
#define USER_DATA_SEG 0x18
#define KERNEL_CODE_SEG 0x20
#define KERNEL_DATA_SEG 0x28
#define LDT_SELECTOR 0x30
#define TASK_SEG 0x38
#define DUMMY_SEG 0x40
#define LAST_SEG (DUMMY_SEG+8)
#define LAST_SEG (TASK_SEG+(NUM_SMPS*8))

#define USER_CODE_SEG_IN_LDT 0x0
#define USER_DATA_SEG_IN_LDT 0x8
Expand Down
24 changes: 20 additions & 4 deletions smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@
#include "util.h"
#include "system.h"
#include "apic.h"
#include "krnlconst.h"

#define AP_INIT_PHYS_TEXT 0xf000
#define AP_COUNT_PHYS_ADDR 0xfff8
#define AP_INIT_PHYS_TEXT 0x7c00

extern int mp_init_size;
extern int init_ap;
extern int init_ap_size;

extern int lapic_base_register;

extern int _kernel_stack_ap_start;
extern int _kernel_pg_dir;
extern int _kernel_pg_table_0;

void copy_smp_init_to_low_mem() {

char *s = (char*)&init_ap;
char *d = (char*)(AP_INIT_PHYS_TEXT+KERNEL_VIRT_ADDR);

for(int i=0;i<(int)&mp_init_size;i++) {
print_msg("init_ap_size", (int)init_ap_size, 10, true);

for(int i=0;i<(int)init_ap_size;i++) {
*d++ = *s++;
}
}
Expand All @@ -36,6 +44,14 @@ void smp_start() {
// initialize AP processor count with 0
// it will be increased by AP startup code
*(int*)(AP_COUNT_PHYS_ADDR+KERNEL_VIRT_ADDR) = 0;
*(int*)(AP_FIRST_STACK+KERNEL_VIRT_ADDR) = (int)&_kernel_stack_ap_start;
*(int*)(AP_LAPIC_BASE_REGISTER+KERNEL_VIRT_ADDR) = (int)&lapic_base_register;
*(int*)(AP_KERNEL_PG_DIR+KERNEL_VIRT_ADDR) = (((int)&_kernel_pg_dir)-KERNEL_VIRT_ADDR);

// identity mapping to enable APs to use paging.
// It needs to be cleared after APs are initialized or it usermode programs
// sharing this page directory cannot access first 4MB virtual memory.
((int*)&_kernel_pg_dir)[0] = (((int)&_kernel_pg_table_0) - KERNEL_VIRT_ADDR) | 3;

MFENCE;

Expand Down
8 changes: 4 additions & 4 deletions system.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int vga_buffer_line = 0;
//
void print_vga(char *c, bool newline) {

unsigned short *p = (unsigned short *)((char*)VIDEO_BUFFER+vga_buffer_index+(vga_buffer_line*160));
unsigned short *p = (unsigned short *)((char*)VIDEO_VIRT_BUFFER+vga_buffer_index+(vga_buffer_line*160));

while(*c) {

Expand All @@ -52,7 +52,7 @@ void print_vga(char *c, bool newline) {

void print_vga_fixed(char *c, int col, int row) {

unsigned short *p = (unsigned short *)((char*)VIDEO_BUFFER+col+(row*160));
unsigned short *p = (unsigned short *)((char*)VIDEO_VIRT_BUFFER+col+(row*160));

while(*c) {

Expand All @@ -75,8 +75,8 @@ void print_vga_fixed(char *c, int col, int row) {
void dump_e820() {

int i;
int e820_count= *((int *) E820_MAP_COUNT);
struct e820_map *e820 = (struct e820_map *) E820_MAP_ADDRESS;
int e820_count= *((int *) E820_MAP_VIRT_COUNT);
struct e820_map *e820 = (struct e820_map *) E820_MAP_VIRT_ADDRESS;
char str[17];

print_vga("E820 map", true);
Expand Down
8 changes: 4 additions & 4 deletions system.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
#define _SYSTEM_H

#include "type.h"
#include "krnlconst.h"

#define KERNEL_VIRT_ADDR 0x80000000
#define VIDEO_BUFFER (KERNEL_VIRT_ADDR+0xb8000)
#define E820_MAP_ADDRESS (KERNEL_VIRT_ADDR+0x1008)
#define E820_MAP_COUNT (KERNEL_VIRT_ADDR+0x1004)
#define VIDEO_VIRT_BUFFER (KERNEL_VIRT_ADDR+VIDEO_BUFFER)
#define E820_MAP_VIRT_ADDRESS (KERNEL_VIRT_ADDR+E820_MAP_ADDRESS)
#define E820_MAP_VIRT_COUNT (KERNEL_VIRT_ADDR+E820_MAP_COUNT)

#define PIT_CRYSTAL_FREQUENCY 1193182
#define PIT_HZ (PIT_CRYSTAL_FREQUENCY/1000)
Expand Down

0 comments on commit ad05c52

Please sign in to comment.