Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to...

36

Transcript of Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to...

Page 1: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll
Page 2: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

1.1

1.2

1.3

1.4

1.5

1.6

1.7

1.8

1.9

1.10

1.11

1.12

1.13

1.14

1.15

1.16

1.17

1.18

1.19

1.20

1.21

TableofContentsIntroduction

Introductionaboutthex86architectureandaboutourOS

Setupthedevelopmentenvironment

FirstbootwithGRUB

BackboneoftheOSandC++runtime

Baseclassesformanagingx86architecture

GDT

IDTandinterrupts

Theory:physicalandvirtualmemory

Memorymanagement:physicalandvirtual

Processmanagementandmultitasking

Externalprogramexecution:ELFfiles

Userlandandsyscalls

Modulardrivers

Somebasicsmodules:console,keyboard

IDEHarddisks

DOSPartitions

EXT2read-onlyfilesystems

StandardClibrary(libC)

UNIXbasictools:sh,cat

Luainterpreter

2

Page 3: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

HowtoMakeaComputerOperatingSystemOnlinebookabouthowtowriteacomputeroperatingsysteminC/C++fromscratch.

Caution:Thisrepositoryisaremakeofmyoldcourse.ItwaswrittenseveralyearsagoasoneofmyfirstprojectswhenIwasinHighSchool,I'mstillrefactoringsomeparts.TheoriginalcoursewasinFrenchandI'mnotanEnglishnative.I'mgoingtocontinueandimprovethiscourseinmyfree-time.

Book:Anonlineversionisavailableathttp://samypesse.gitbooks.io/how-to-create-an-operating-system/(PDF,MobiandePub).ItwasgeneratedusingGitBook.

SourceCode:Allthesystemsourcecodewillbestoredinthesrcdirectory.Eachstepwillcontainlinkstothedifferentrelatedfiles.

Contributions:Thiscourseisopentocontributions,feelfreetosignalerrorswithissuesordirectlycorrecttheerrorswithpull-requests.

Questions:Feelfreetoaskanyquestionsbyaddingissuesorcommentingsections.

YoucanfollowmeonTwitter@SamyPesseorGitHub.

WhatkindofOSarewebuilding?

ThegoalistobuildaverysimpleUNIX-basedoperatingsysteminC++,notjusta"proof-of-concept".TheOSshouldbeabletoboot,startauserlandshell,andbeextensible.

Introduction

3

Page 4: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Introduction

4

Page 5: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter1:Introductiontothex86architectureandaboutourOS

Whatisthex86architecture?

Thetermx86denotesafamilyofbackwardcompatibleinstructionsetarchitecturesbasedontheIntel8086CPU.

Thex86architectureisthemostcommoninstructionsetarchitecturesinceitsintroductionin1981fortheIBMPC.Alargeamountofsoftware,includingoperatingsystems(OS's)suchasDOS,Windows,Linux,BSD,SolarisandMacOSX,functionwithx86-basedhardware.

Inthiscoursewearenotgoingtodesignanoperatingsystemforthex86-64architecturebutforx86-32,thankstobackwardcompatibility,ourOSwillbecompatiblewithournewerPCs(buttakecautionifyouwanttotestitonyourrealmachine).

OurOperatingSystem

ThegoalistobuildaverysimpleUNIX-basedoperatingsysteminC++,butthegoalisnottojustbuilda"proof-of-concept".TheOSshouldbeabletoboot,startauserlandshellandbeextensible.

TheOSwillbebuiltforthex86architecture,runningon32bits,andcompatiblewithIBMPCs.

Specifications:

CodeinC++x86,32bitarchitectureBootwithGrubKindofmodularsystemfordriversKindofUNIXstyleMultitaskingELFexecutableinuserlandModules(accessibleinuserlandusing/dev/...):

IDEdisksDOSpartitionsClockEXT2(readonly)BochVBE

Userland:

Introductionaboutthex86architectureandaboutourOS

5

Page 6: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

APIPosixLibC"Can"runashellorsomeexecutables(e.g.,lua)

Introductionaboutthex86architectureandaboutourOS

6

Page 7: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter2:SetupthedevelopmentenvironmentThefirststepistosetupagoodandviabledevelopmentenvironment.UsingVagrantandVirtualbox,you'llbeabletocompileandtestyourOSfromalltheOSs(Linux,WindowsorMac).

InstallVagrant

Vagrantisfreeandopen-sourcesoftwareforcreatingandconfiguringvirtualdevelopmentenvironments.ItcanbeconsideredawrapperaroundVirtualBox.

Vagrantwillhelpuscreateacleanvirtualdevelopmentenvironmentonwhateversystemyouareusing.ThefirststepistodownloadandinstallVagrantforyoursystemathttp://www.vagrantup.com/.

InstallVirtualbox

OracleVMVirtualBoxisavirtualizationsoftwarepackageforx86andAMD64/Intel64-basedcomputers.

VagrantneedsVirtualboxtowork,Downloadandinstallforyoursystemathttps://www.virtualbox.org/wiki/Downloads.

Startandtestyourdevelopmentenvironment

OnceVagrantandVirtualboxareinstalled,youneedtodownloadtheubuntulucid32imageforVagrant:

vagrantboxaddlucid32http://files.vagrantup.com/lucid32.box

Oncethelucid32imageisready,weneedtodefineourdevelopmentenvironmentusingaVagrantfile,createafilenamedVagrantfile.Thisfiledefineswhatprerequisitesourenvironmentneeds:nasm,make,build-essential,grubandqemu.

Startyourboxusing:

vagrantup

Youcannowaccessyourboxbyusingsshtoconnecttothevirtualboxusing:

Setupthedevelopmentenvironment

7

Page 8: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

vagrantssh

ThedirectorycontainingtheVagrantfilewillbemountedbydefaultinthe/vagrantdirectoryoftheguestVM(inthiscase,UbuntuLucid32):

cd/vagrant

Buildandtestouroperatingsystem

ThefileMakefiledefinessomebasicsrulesforbuildingthekernel,theuserlibcandsomeuserlandprograms.

Build:

makeall

Testouroperatingsystemwithqemu:

makerun

ThedocumentationforqemuisavailableatQEMUEmulatorDocumentation.

Youcanexittheemulatorusing:Ctrl-a.

Setupthedevelopmentenvironment

8

Page 9: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter3:FirstbootwithGRUB

Howthebootworks?

Whenanx86-basedcomputeristurnedon,itbeginsacomplexpathtogettothestagewherecontrolistransferredtoourkernel's"main"routine(kmain()).Forthiscourse,weareonlygoingtoconsidertheBIOSbootmethodandnotit'ssuccessor(UEFI).

TheBIOSbootsequenceis:RAMdetection->Hardwaredetection/Initialization->Bootsequence.

Themostimportantstepforusisthe"Bootsequence",wheretheBIOSisdonewithitsinitializationandtriestotransfercontroltothenextstageofthebootloaderprocess.

Duringthe"Bootsequence",theBIOSwilltrytodeterminea"bootdevice"(e.g.floppydisk,hard-disk,CD,USBflashmemorydeviceornetwork).OurOperatingSystemwillinitiallybootfromthehard-disk(butitwillbepossibletobootitfromaCDoraUSBflashmemorydeviceinfuture).Adeviceisconsideredbootableifthebootsectorcontainsthevalidsignaturebytes0x55and0xAAatoffsets511and512respectively(calledthemagicbytesoftheMasterBootRecord,alsoknownastheMBR).Thissignatureisrepresented(inbinary)as0b1010101001010101.Thealternatingbitpatternwasthoughttobeaprotectionagainstcertainfailures(driveorcontroller).Ifthispatternisgarbledor0x00,thedeviceisnotconsideredbootable.

BIOSphysicallysearchesforabootdevicebyloadingthefirst512bytesfromthebootsectorofeachdeviceintophysicalmemory,startingattheaddress0x7C00(1KiBbelowthe32KiBmark).Whenthevalidsignaturebytesaredetected,BIOStransferscontroltothe0x7C00memoryaddress(viaajumpinstruction)inordertoexecutethebootsectorcode.

ThroughoutthisprocesstheCPUhasbeenrunningin16-bitRealMode,whichisthedefaultstateforx86CPUsinordertomaintainbackwardscompatibility.Toexecutethe32-bitinstructionswithinourkernel,abootloaderisrequiredtoswitchtheCPUintoProtectedMode.

WhatisGRUB?

GNUGRUB(shortforGNUGRandUnifiedBootloader)isabootloaderpackagefromtheGNUProject.GRUBisthereferenceimplementationoftheFreeSoftwareFoundation'sMultibootSpecification,whichprovidesauserthechoicetobootoneofmultipleoperatingsystemsinstalledonacomputerorselectaspecifickernelconfigurationavailableonaparticularoperatingsystem'spartitions.

FirstbootwithGRUB

9

Page 10: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Tomakeitsimple,GRUBisthefirstthingbootedbythemachine(aboot-loader)andwillsimplifytheloadingofourkernelstoredonthehard-disk.

WhyareweusingGRUB?

GRUBisverysimpletouseMakeitverysimpletoload32bitskernelswithoutneedsof16bitscodeMultibootwithLinux,WindowsandothersMakeiteasytoloadexternalmodulesinmemory

HowtouseGRUB?

GRUBusestheMultibootspecification,theexecutablebinaryshouldbe32bitsandmustcontainaspecialheader(multibootheader)inits8192firstbytes.OurkernelwillbeaELFexecutablefile("ExecutableandLinkableFormat",acommonstandardfileformatforexecutablesinmostUNIXsystem).

ThefirstbootsequenceofourkerneliswritteninAssembly:start.asmandweusealinkerfiletodefineourexecutablestructure:linker.ld.

ThisbootprocessalsoinitializessomeofourC++runtime,itwillbedescribedinthenextchapter.

Multibootheaderstructure:

FirstbootwithGRUB

10

Page 11: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

structmultiboot_info{

u32flags;

u32low_mem;

u32high_mem;

u32boot_device;

u32cmdline;

u32mods_count;

u32mods_addr;

struct{

u32num;

u32size;

u32addr;

u32shndx;

}elf_sec;

unsignedlongmmap_length;

unsignedlongmmap_addr;

unsignedlongdrives_length;

unsignedlongdrives_addr;

unsignedlongconfig_table;

unsignedlongboot_loader_name;

unsignedlongapm_table;

unsignedlongvbe_control_info;

unsignedlongvbe_mode_info;

unsignedlongvbe_mode;

unsignedlongvbe_interface_seg;

unsignedlongvbe_interface_off;

unsignedlongvbe_interface_len;

};

Youcanusethecommandmbchkkernel.elftovalidateyourkernel.elffileagainstthemultibootstandard.Youcanalsousethecommandnm-nkernel.elftovalidatetheoffsetofthedifferentobjectsintheELFbinary.

Createadiskimageforourkernelandgrub

Thescriptdiskimage.shwillgenerateaharddiskimagethatcanbeusedbyQEMU.

Thefirststepistocreateahard-diskimage(c.img)usingqemu-img:

qemu-imgcreatec.img2M

Weneednowtopartitionthediskusingfdisk:

FirstbootwithGRUB

11

Page 12: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

fdisk./c.img

#SwitchtoExpertcommands

>x

#Changenumberofcylinders(1-1048576)

>c

>4

#Changenumberofheads(1-256,default16):

>h

>16

#Changenumberofsectors/track(1-63,default63)

>s

>63

#Returntomainmenu

>r

#Addanewpartition

>n

#Chooseprimarypartition

>p

#Choosepartitionnumber

>1

#Choosefirstsector(1-4,default1)

>1

#Chooselastsector,+cylindersor+size{K,M,G}(1-4,default4)

>4

#Togglebootableflag

>a

#Choosefirstpartitionforbootableflag

>1

#Writetabletodiskandexit

>w

Weneednowtoattachthecreatedpartitiontotheloop-deviceusinglosetup.Thisallowsafiletobeaccesslikeablockdevice.Theoffsetofthepartitionispassedasanargumentandcalculatedusing:offset=start_sector*bytes_by_sector.

Usingfdisk-l-uc.img,youget:63*512=32256.

FirstbootwithGRUB

12

Page 13: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

losetup-o32256/dev/loop1./c.img

WecreateaEXT2filesystemonthisnewdeviceusing:

mke2fs/dev/loop1

Wecopyourfilesonamounteddisk:

mount/dev/loop1/mnt/

cp-Rbootdisk/*/mnt/

umount/mnt/

InstallGRUBonthedisk:

grub--device-map=/dev/null<<EOF

device(hd0)./c.img

geometry(hd0)41663

root(hd0,0)

setup(hd0)

quit

EOF

Andfinallywedetachtheloopdevice:

losetup-d/dev/loop1

SeeAlso

GNUGRUBonWikipediaMultibootspecification

FirstbootwithGRUB

13

Page 14: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter4:BackboneoftheOSandC++runtime

C++kernelrun-time

AkernelcanbewritteninC++justasitcanbeinC,withtheexceptionofafewpitfallsthatcomewithusingC++(runtimesupport,constructors,etc).

ThecompilerwillassumethatallthenecessaryC++runtimesupportisavailablebydefault,butaswearenotlinkinglibsupc++intoyourC++kernel,weneedtoaddsomebasicfunctionsthatcanbefoundinthecxx.ccfile.

Caution:Theoperatorsnewanddeletecannotbeusedbeforevirtualmemoryandpaginationhavebeeninitialized.

BasicC/C++functions

Thekernelcodecan'tusefunctionsfromthestandardlibrariessoweneedtoaddsomebasicfunctionsformanagingmemoryandstrings:

voiditoa(char*buf,unsignedlongintn,intbase);

void*memset(char*dst,charsrc,intn);

void*memcpy(char*dst,char*src,intn);

intstrlen(char*s);

intstrcmp(constchar*dst,char*src);

intstrcpy(char*dst,constchar*src);

voidstrcat(void*dest,constvoid*src);

char*strncpy(char*destString,constchar*sourceString,intmaxLength);

intstrncmp(constchar*s1,constchar*s2,intc);

Thesefunctionsaredefinedinstring.cc,memory.cc,itoa.cc

Ctypes

Inthenextstep,we'regoingtodefinedifferenttypeswe'regoingtouseinourcode.Mostofourvariabletypesaregoingtobeunsigned.Thismeansthatallthebitsareusedtostoretheinteger.Signedvariablesusetheirfirstbittoindicatetheirsign.

BackboneoftheOSandC++runtime

14

Page 15: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

typedefunsignedcharu8;

typedefunsignedshortu16;

typedefunsignedintu32;

typedefunsignedlonglongu64;

typedefsignedchars8;

typedefsignedshorts16;

typedefsignedints32;

typedefsignedlonglongs64;

Compileourkernel

Compilingakernelisnotthesamethingascompilingalinuxexecutable,wecan'tuseastandardlibraryandshouldhavenodependenciestothesystem.

OurMakefilewilldefinetheprocesstocompileandlinkourkernel.

Forx86architecture,thefollowingsargumentswillbeusedforgcc/g++/ld:

#Linker

LD=ld

LDFLAG=-melf_i386-static-L./-T./arch/$(ARCH)/linker.ld

#C++compiler

SC=g++

FLAG=$(INCDIR)-g-O2-w-trigraphs-fno-builtin-fno-exceptions-fno-stack-protecto

r-O0-m32-fno-rtti-nostdlib-nodefaultlibs

#Assemblycompiler

ASM=nasm

ASMFLAG=-felf-o

BackboneoftheOSandC++runtime

15

Page 16: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter5:Baseclassesformanagingx86architectureNowthatweknowhowtocompileourC++kernelandbootthebinaryusingGRUB,wecanstarttodosomecoolthingsinC/C++.

Printingtothescreenconsole

WearegoingtouseVGAdefaultmode(03h)todisplaysometexttotheuser.Thescreencanbedirectlyaccessedusingthevideomemoryat0xB8000.Thescreenresolutionis80x25andeachcharacteronthescreenisdefinedby2bytes:oneforthecharactercode,andoneforthestyleflag.Thismeansthatthetotalsizeofthevideomemoryis4000B(80B25B2B).

IntheIOclass(io.cc),:

x,y:definethecursorpositiononthescreenreal_screen:definethevideomemorypointerputc(charc):printauniquecharacteronthescreenandmanagecursorpositionprintf(char*s,...):printastring

WeaddamethodputctotheIOClasstoputacharacteronthescreenandupdatethe(x,y)position.

Baseclassesformanagingx86architecture

16

Page 17: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

/*putabyteonscreen*/

voidIo::putc(charc){

kattr=0x07;

unsignedchar*video;

video=(unsignedchar*)(real_screen+2*x+160*y);

//newline

if(c=='\n'){

x=0;

y++;

//backspace

}elseif(c=='\b'){

if(x){

*(video+1)=0x0;

x--;

}

//horizontaltab

}elseif(c=='\t'){

x=x+8-(x%8);

//carriagereturn

}elseif(c=='\r'){

x=0;

}else{

*video=c;

*(video+1)=kattr;

x++;

if(x>79){

x=0;

y++;

}

}

if(y>24)

scrollup(y-24);

}

Wealsoaddausefulandveryknownmethod:printf

/*putastringinscreen*/

voidIo::print(constchar*s,...){

va_listap;

charbuf[16];

inti,j,size,buflen,neg;

unsignedcharc;

intival;

unsignedintuival;

va_start(ap,s);

while((c=*s++)){

Baseclassesformanagingx86architecture

17

Page 18: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

size=0;

neg=0;

if(c==0)

break;

elseif(c=='%'){

c=*s++;

if(c>='0'&&c<='9'){

size=c-'0';

c=*s++;

}

if(c=='d'){

ival=va_arg(ap,int);

if(ival<0){

uival=0-ival;

neg++;

}else

uival=ival;

itoa(buf,uival,10);

buflen=strlen(buf);

if(buflen<size)

for(i=size,j=buflen;i>=0;

i--,j--)

buf[i]=

(j>=

0)?buf[j]:'0';

if(neg)

print("-%s",buf);

else

print(buf);

}

elseif(c=='u'){

uival=va_arg(ap,int);

itoa(buf,uival,10);

buflen=strlen(buf);

if(buflen<size)

for(i=size,j=buflen;i>=0;

i--,j--)

buf[i]=

(j>=

0)?buf[j]:'0';

print(buf);

}elseif(c=='x'||c=='X'){

uival=va_arg(ap,int);

itoa(buf,uival,16);

buflen=strlen(buf);

if(buflen<size)

Baseclassesformanagingx86architecture

18

Page 19: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

for(i=size,j=buflen;i>=0;

i--,j--)

buf[i]=

(j>=

0)?buf[j]:'0';

print("0x%s",buf);

}elseif(c=='p'){

uival=va_arg(ap,int);

itoa(buf,uival,16);

size=8;

buflen=strlen(buf);

if(buflen<size)

for(i=size,j=buflen;i>=0;

i--,j--)

buf[i]=

(j>=

0)?buf[j]:'0';

print("0x%s",buf);

}elseif(c=='s'){

print((char*)va_arg(ap,int));

}

}else

putc(c);

}

return;

}

Assemblyinterface

AlargenumberofinstructionsareavailableinAssemblybutthereisnotequivalentinC(likecli,sti,inandout),soweneedaninterfacetotheseinstructions.

InC,wecanincludeAssemblyusingthedirective"asm()",gccusegastocompiletheassembly.

Caution:gasusestheAT&Tsyntax.

Baseclassesformanagingx86architecture

19

Page 20: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

/*outputbyte*/

voidIo::outb(u32ad,u8v){

asmv("outb%%al,%%dx"::"d"(ad),"a"(v));;

}

/*outputword*/

voidIo::outw(u32ad,u16v){

asmv("outw%%ax,%%dx"::"d"(ad),"a"(v));

}

/*outputword*/

voidIo::outl(u32ad,u32v){

asmv("outl%%eax,%%dx"::"d"(ad),"a"(v));

}

/*inputbyte*/

u8Io::inb(u32ad){

u8_v;\

asmv("inb%%dx,%%al":"=a"(_v):"d"(ad));\

return_v;

}

/*inputword*/

u16Io::inw(u32ad){

u16_v;\

asmv("inw%%dx,%%ax":"=a"(_v):"d"(ad));\

return_v;

}

/*inputword*/

u32Io::inl(u32ad){

u32_v;\

asmv("inl%%dx,%%eax":"=a"(_v):"d"(ad));\

return_v;

}

Baseclassesformanagingx86architecture

20

Page 21: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter6:GDTThankstoGRUB,yourkernelisnolongerinreal-mode,butalreadyinprotectedmode,thismodeallowsustouseallthepossibilitiesofthemicroprocessorsuchasvirtualmemorymanagement,pagingandsafemulti-tasking.

WhatistheGDT?

TheGDT("GlobalDescriptorTable")isadatastructureusedtodefinethedifferentmemoryareas:thebaseaddress,thesizeandaccessprivilegeslikeexecuteandwrite.Thesememoryareasarecalled"segments".

WearegoingtousetheGDTtodefinedifferentmemorysegments:

"code":kernelcode,usedtostoredtheexecutablebinarycode"data":kerneldata"stack":kernelstack,usedtostoredthecallstackduringkernelexecution"ucode":usercode,usedtostoredtheexecutablebinarycodeforuserprogram"udata":userprogramdata"ustack":userstack,usedtostoredthecallstackduringexecutioninuserland

HowtoloadourGDT?

GRUBinitializesaGDTbutthisGDTisdoesnotcorrespondtoourkernel.TheGDTisloadedusingtheLGDTassemblyinstruction.ItexpectsthelocationofaGDTdescriptionstructure:

AndtheCstructure:

GDT

21

Page 22: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

structgdtr{

u16limite;

u32base;

}__attribute__((packed));

Caution:thedirective__attribute__((packed))signaltogccthatthestructureshoulduseaslittlememoryaspossible.Withoutthisdirective,gccincludesomebytestooptimizethememoryalignmentandtheaccessduringexecution.

NowweneedtodefineourGDTtableandthenloaditusingLGDT.TheGDTtablecanbestoredwhereverwewantinmemory,itsaddressshouldjustbesignaledtotheprocessusingtheGDTRregistry.

TheGDTtableiscomposedofsegmentswiththefollowingstructure:

AndtheCstructure:

structgdtdesc{

u16lim0_15;

u16base0_15;

u8base16_23;

u8acces;

u8lim16_19:4;

u8other:4;

u8base24_31;

}__attribute__((packed));

HowtodefineourGDTtable?

WeneednowtodefineourGDTinmemoryandfinallyloaditusingtheGDTRregistry.

WearegoingtostoreourGDTattheaddress:

#defineGDTBASE0x00000800

GDT

22

Page 23: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Thefunctioninit_gdt_descinx86.ccinitializeagdtsegmentdescriptor.

voidinit_gdt_desc(u32base,u32limite,u8acces,u8other,structgdtdesc*desc)

{

desc->lim0_15=(limite&0xffff);

desc->base0_15=(base&0xffff);

desc->base16_23=(base&0xff0000)>>16;

desc->acces=acces;

desc->lim16_19=(limite&0xf0000)>>16;

desc->other=(other&0xf);

desc->base24_31=(base&0xff000000)>>24;

return;

}

Andthefunctioninit_gdtinitializetheGDT,somepartsofthebelowfunctionwillbeexplainedlaterandareusedformultitasking.

GDT

23

Page 24: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

voidinit_gdt(void)

{

default_tss.debug_flag=0x00;

default_tss.io_map=0x00;

default_tss.esp0=0x1FFF0;

default_tss.ss0=0x18;

/*initializegdtsegments*/

init_gdt_desc(0x0,0x0,0x0,0x0,&kgdt[0]);

init_gdt_desc(0x0,0xFFFFF,0x9B,0x0D,&kgdt[1]);/*code*/

init_gdt_desc(0x0,0xFFFFF,0x93,0x0D,&kgdt[2]);/*data*/

init_gdt_desc(0x0,0x0,0x97,0x0D,&kgdt[3]);/*stack*/

init_gdt_desc(0x0,0xFFFFF,0xFF,0x0D,&kgdt[4]);/*ucode*/

init_gdt_desc(0x0,0xFFFFF,0xF3,0x0D,&kgdt[5]);/*udata*/

init_gdt_desc(0x0,0x0,0xF7,0x0D,&kgdt[6]);/*ustack*/

init_gdt_desc((u32)&default_tss,0x67,0xE9,0x00,&kgdt[7]);/*descripteur

detss*/

/*initializethegdtrstructure*/

kgdtr.limite=GDTSIZE*8;

kgdtr.base=GDTBASE;

/*copythegdtrtoitsmemoryarea*/

memcpy((char*)kgdtr.base,(char*)kgdt,kgdtr.limite);

/*loadthegdtrregistry*/

asm("lgdtl(kgdtr)");

/*initiliazthesegments*/

asm("movw$0x10,%ax\n\

movw%ax,%ds\n\

movw%ax,%es\n\

movw%ax,%fs\n\

movw%ax,%gs\n\

ljmp$0x08,$next\n\

next:\n");

}

GDT

24

Page 25: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter7:IDTandinterruptsAninterruptisasignaltotheprocessoremittedbyhardwareorsoftwareindicatinganeventthatneedsimmediateattention.

Thereare3typesofinterrupts:

Hardwareinterrupts:aresenttotheprocessorfromanexternaldevice(keyboard,mouse,harddisk,...).Hardwareinterruptswereintroducedasawaytoreducewastingtheprocessor'svaluabletimeinpollingloops,waitingforexternalevents.Softwareinterrupts:areinitiatedvoluntarilybythesoftware.It'susedtomanagesystemcalls.Exceptions:areusedforerrorsoreventsoccurringduringprogramexecutionthatareexceptionalenoughthattheycannotbehandledwithintheprogramitself(divisionbyzero,pagefault,...)

Thekeyboardexample:

Whentheuserpressedakeyonthekeyboard,thekeyboardcontrollerwillsignalaninterrupttotheInterruptController.Iftheinterruptisnotmasked,thecontrollerwillsignaltheinterrupttotheprocessor,theprocessorwillexecutearoutinetomanagetheinterrupt(keypressedorkeyreleased),thisroutinecould,forexample,getthepressedkeyfromthekeyboardcontrollerandprintthekeytothescreen.Oncethecharacterprocessingroutineiscompleted,theinterruptedjobcanberesumed.

WhatisthePIC?

ThePIC(Programmableinterruptcontroller)isadevicethatisusedtocombineseveralsourcesofinterruptontooneormoreCPUlines,whileallowingprioritylevelstobeassignedtoitsinterruptoutputs.Whenthedevicehasmultipleinterruptoutputstoassert,itassertsthemintheorderoftheirrelativepriority.

ThebestknownPICisthe8259A,each8259Acanhandle8devicesbutmostcomputershavetwocontrollers:onemasterandoneslave,thisallowsthecomputertomanageinterruptsfrom14devices.

Inthischapter,wewillneedtoprogramthiscontrollertoinitializeandmaskinterrupts.

WhatistheIDT?

IDTandinterrupts

25

Page 26: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

TheInterruptDescriptorTable(IDT)isadatastructureusedbythex86architecturetoimplementaninterruptvectortable.TheIDTisusedbytheprocessortodeterminethecorrectresponsetointerruptsandexceptions.

OurkernelisgoingtousetheIDTtodefinethedifferentfunctionstobeexecutedwhenaninterruptoccurred.

LiketheGDT,theIDTisloadedusingtheLIDTLassemblyinstruction.ItexpectsthelocationofaIDTdescriptionstructure:

structidtr{

u16limite;

u32base;

}__attribute__((packed));

TheIDTtableiscomposedofIDTsegmentswiththefollowingstructure:

structidtdesc{

u16offset0_15;

u16select;

u16type;

u16offset16_31;

}__attribute__((packed));

Caution:thedirective__attribute__((packed))signaltogccthatthestructureshoulduseaslittlememoryaspossible.Withoutthisdirective,gccincludessomebytestooptimizethememoryalignmentandtheaccessduringexecution.

NowweneedtodefineourIDTtableandthenloaditusingLIDTL.TheIDTtablecanbestoredwhereverwewantinmemory,itsaddressshouldjustbesignaledtotheprocessusingtheIDTRregistry.

Hereisatableofcommoninterrupts(MaskablehardwareinterruptarecalledIRQ):

IDTandinterrupts

26

Page 27: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

IRQ Description

0 ProgrammableInterruptTimerInterrupt

1 KeyboardInterrupt

2 Cascade(usedinternallybythetwoPICs.neverraised)

3 COM2(ifenabled)

4 COM1(ifenabled)

5 LPT2(ifenabled)

6 FloppyDisk

7 LPT1

8 CMOSreal-timeclock(ifenabled)

9 Freeforperipherals/legacySCSI/NIC

10 Freeforperipherals/SCSI/NIC

11 Freeforperipherals/SCSI/NIC

12 PS2Mouse

13 FPU/Coprocessor/Inter-processor

14 PrimaryATAHardDisk

15 SecondaryATAHardDisk

Howtoinitializetheinterrupts?

ThisisasimplemethodtodefineanIDTsegment

voidinit_idt_desc(u16select,u32offset,u16type,structidtdesc*desc)

{

desc->offset0_15=(offset&0xffff);

desc->select=select;

desc->type=type;

desc->offset16_31=(offset&0xffff0000)>>16;

return;

}

Andwecannowinitializetheinterupts:

#defineIDTBASE0x00000000

#defineIDTSIZE0xFF

idtrkidtr;

IDTandinterrupts

27

Page 28: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

voidinit_idt(void)

{

/*Initirq*/

inti;

for(i=0;i<IDTSIZE;i++)

init_idt_desc(0x08,(u32)_asm_schedule,INTGATE,&kidt[i]);//

/*Vectors0->31areforexceptions*/

init_idt_desc(0x08,(u32)_asm_exc_GP,INTGATE,&kidt[13]);/*#GP*/

init_idt_desc(0x08,(u32)_asm_exc_PF,INTGATE,&kidt[14]);/*#PF*/

init_idt_desc(0x08,(u32)_asm_schedule,INTGATE,&kidt[32]);

init_idt_desc(0x08,(u32)_asm_int_1,INTGATE,&kidt[33]);

init_idt_desc(0x08,(u32)_asm_syscalls,TRAPGATE,&kidt[48]);

init_idt_desc(0x08,(u32)_asm_syscalls,TRAPGATE,&kidt[128]);//48

kidtr.limite=IDTSIZE*8;

kidtr.base=IDTBASE;

/*CopytheIDTtothememory*/

memcpy((char*)kidtr.base,(char*)kidt,kidtr.limite);

/*LoadtheIDTRregistry*/

asm("lidtl(kidtr)");

}

AfterintializationofourIDT,weneedtoactivateinterruptsbyconfiguringthePIC.ThefollowingfunctionwillconfigurethetwoPICsbywrittingintheirinternalregistriesusingtheoutputportsoftheprocessorio.outb.WeconfigurethePICsusingtheports:

MasterPIC:0x20and0x21SlavePIC:0xA0and0xA1

ForaPIC,thereare2typesofregistries:

ICW(InitializationCommandWord):reinitthecontrollerOCW(OperationControlWord):configurethecontrolleronceinitialized(usedtomask/unmasktheinterrupts)

IDTandinterrupts

28

Page 29: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

voidinit_pic(void)

{

/*InitializationofICW1*/

io.outb(0x20,0x11);

io.outb(0xA0,0x11);

/*InitializationofICW2*/

io.outb(0x21,0x20);/*startvector=32*/

io.outb(0xA1,0x70);/*startvector=96*/

/*InitializationofICW3*/

io.outb(0x21,0x04);

io.outb(0xA1,0x02);

/*InitializationofICW4*/

io.outb(0x21,0x01);

io.outb(0xA1,0x01);

/*maskinterrupts*/

io.outb(0x21,0x0);

io.outb(0xA1,0x0);

}

PICICWconfigurationsdetails

Theregistrieshavetobeconfiguredinorder.

ICW1(port0x20/port0xA0)

|0|0|0|1|x|0|x|x|

||+---withICW4(1)orwithout(0)

|+-----onecontroller(1),orcascade(0)

+---------triggeringbylevel(level)(1)orbyedge(edge)(0)

ICW2(port0x21/port0xA1)

|x|x|x|x|x|0|0|0|

|||||

+-----------------baseaddressforinterruptsvectors

ICW2(port0x21/port0xA1)

Forthemaster:

IDTandinterrupts

29

Page 30: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

|x|x|x|x|x|x|x|x|

||||||||

+------------------slavecontrollerconnectedtotheportyes(1),orno(0)

Fortheslave:

|0|0|0|0|0|x|x|x|pourl'esclave

|||

+--------SlaveIDwhichisequaltothemasterport

ICW4(port0x21/port0xA1)

Itisusedtodefineinwhichmodethecontrollershouldwork.

|0|0|0|x|x|x|x|1|

|||+------mode"automaticendofinterrupt"AEOI(1)

||+--------modebufferedslave(0)ormaster(1)

|+----------modebuffered(1)

+------------mode"fullynested"(1)

WhydoidtsegmentsoffsetourASMfunctions?

YoushouldhavenoticedthatwhenI'minitializingourIDTsegments,I'musingoffsetstosegmentthecodeinAssembly.Thedifferentfunctionsaredefinedinx86int.asmandareofthefollowingscheme:

IDTandinterrupts

30

Page 31: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

%macroSAVE_REGS0

pushad

pushds

pushes

pushfs

pushgs

pushebx

movbx,0x10

movds,bx

popebx

%endmacro

%macroRESTORE_REGS0

popgs

popfs

popes

popds

popad

%endmacro

%macroINTERRUPT1

global_asm_int_%1

_asm_int_%1:

SAVE_REGS

push%1

callisr_default_int

popeax;;aenleversinon

moval,0x20

out0x20,al

RESTORE_REGS

iret

%endmacro

Thesemacroswillbeusedtodefinetheinterruptsegmentthatwillpreventcorruptionofthedifferentregistries,itwillbeveryusefulformultitasking.

IDTandinterrupts

31

Page 32: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Chapter8:Theory:physicalandvirtualmemoryInthechapterrelatedtotheGDT,wesawthatusingsegmentationaphysicalmemoryaddressiscalculatedusingasegmentselectorandanoffset.

Inthischapter,wearegoingtoimplementpaging,pagingwilltranslatealinearaddressfromsegmentationintoaphysicaladdress.

Whydoweneedpaging?

Pagingwillallowourkernelto:

usethehard-driveasamemoryandnotbelimitedbythemachinerammemorylimittohaveauniquememoryspaceforeachprocesstoallowandunallowmemoryspaceinadynamicway

Inapagedsystem,eachprocessmayexecuteinitsown4gbareaofmemory,withoutanychanceofeffectinganyotherprocess'smemory,orthekernel's.Itsimplifiesmultitasking.

Howdoesitwork?

Thetranslationofalinearaddresstoaphysicaladdressisdoneinmultiplesteps:

1. TheprocessorusetheregistryCR3toknowthephysicaladdressofthepagesdirectory.

2. Thefirst10bitsofthelinearaddressrepresentanoffset(between0and1023),pointingtoanentryinthepagesdirectory.Thisentrycontainsthephysicaladdressofapagestable.

3. thenext10bitsofthelinearaddressrepresentanoffset,pointingtoanentryinthepagestable.Thisentryispointingtoa4kopage.

4. Thelast12bitsofthelinearaddressrepresentanoffset(between0and4095),whichindicatesthepositioninthe4kopage.

Theory:physicalandvirtualmemory

32

Page 33: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Formatforpagestableanddirectory

Thetwotypesofentries(tableanddirectory)looklikethesame.OnlythefieldingraywillbeusedinourOS.

P:indicateifthepageortableisinphysicalmemoryR/W:indicateifthepageortableisaccessibleinwritting(equals1)U/S:equals1toallowaccesstonon-preferredtasksA:indicateifthepageortablewasaccessedD:(onlyforpagestable)indicateifthepagewaswrittenPS(onlyforpagesdirectory)indicatethesizeofpages:

0=4kb1=4mb

Note:Physicaladdressesinthepagesdiretcoryorpagestablearewrittenusing20bitsbecausetheseaddressesarealignedon4kb,sothelast12bitsshouldbeequalto0.

Apagesdirectoryorpagestableused1024*4=4096bytes=4k

Theory:physicalandvirtualmemory

33

Page 34: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Apagestablecanaddress1024*4k=4MbApagesdirectorycanaddress1024(10244k)=4Gb

Howtoenablepagination?

Toenablepagination,wejustneedtosetbit31oftheCR0registryto1:

asm("mov%%cr0,%%eax;\

or%1,%%eax;\

mov%%eax,%%cr0"\

::"i"(0x80000000));

Butbefore,weneedtoinitializeourpagesdirectorywithatleastonepagestable.

IdentityMapping

Withtheidentitymappingmodel,thepagewillapplyonlytothekernelasthefirst4MBofvirtualmemorycoincidewiththefirst4MBofphysicalmemory:

Thismodelissimple:thefirstvirtualmemorypagecoincidetothefirstpageinphysicalmemory,thesecondpagecoincidetothesecondpageonphysicalmemoryandsoon...

Theory:physicalandvirtualmemory

34

Page 35: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Memorymanagement:physicalandvirtualThekernelknowsthesizeofthephysicalmemoryavailablethankstoGRUB.

Inourimplementation,thefirst8megabytesofphysicalmemorywillbereservedforusebythekernelandwillcontain:

ThekernelGDT,IDTetTSSKernelStackSomespacereservedtohardware(videomemory,...)Pagedirectoryandpagestableforthekernel

Therestofthephysicalmemoryisfreelyavailabletothekernelandapplications.

VirtualMemoryMapping

Theaddressspacebetweenthebeginningofmemoryand0x40000000addressisthekernelspace,whilethespacebetweentheaddress0x40000000andtheendofthememorycorrespondstouserspace:

Memorymanagement:physicalandvirtual

35

Page 36: Table of Contents - gti.bh · Chapter 2: Setup the development environment The first step is to setup a good and viable development environment. Using Vagrant and Virtualbox, you'll

Thekernelspaceinvirtualmemory,whichisusing1Gbofvirtualmemory,iscommontoalltasks(kernelanduser).

Thisisimplementedbypointingthefirst256entriesofthetaskpagedirectorytothekernelpagedirectory(Invmm.cc):

/*

*KernelSpace.v_addr<USER_OFFSETareaddressedbythekernelpagestable

*/

for(i=0;i<256;i++)

pdir[i]=pd0[i];

Memorymanagement:physicalandvirtual

36