![Contract Post Collapse](//www.dsy.it/forum/images/collapse.gif) |
Cronovirus |
dsy core staff
![](avatar.php?userid=15306&dateline=1402925978)
Registered: Jun 2012
Posts: 471 (0.11 al dì)
Location:
Corso: Magistrale in Informatica
Anno: 2
Time Online: 4 Days, 2:45:03: [...]
Status: Offline
Edit | Report | IP: Logged |
Premetto che è abbastanza complicato spiegare qui e ci sono molte cose da dire.. do per scontato che tu conosca le funzionalità dei registri e dei file .ELF, memoria virtuale etc.. comunque:
/* See COPYRIGHT for copyright information. */
##################################################
#################
Il linker ha compilato gli indirizzi del kernel con indirizzi virtuali, i progettisti di JOS infatti hanno deciso che il kernel occupi l'ultimo GB di memoria centrale (quindi da 3 a 4 GB).
Tuttavia il bootloader ha caricato i primi 4MB del kernel a partire da 1MB di memoria fisica. La funzione RELOC(X) permette di mutare un indirizzo virtuale del kernel nel corrispettivo indirizzo fisico
##################################################
#################
#define RELOC(x) ((x) - KERNBASE)
##################################################
#################
# entry point
##################################################
#################
.text
##################################################
#################
_start è stato specificato nel file .ELF come entry point (prima istruzione da eseguire), tuttavia siccome non è ancora stata abilitata la memoria virtuale bisogna convertire gli indirizzi del kernel in indirizzi fisici: infatti come ho detto prima gli indirizzi del kernel sono stati compilati come indirizzi VIRTUALI, ma siccome non ho ancora la memoria virtuale devo convertire gli indirizzi virtuali in indirizzi fisici "da solo".
##################################################
#################
.globl _start
_start = RELOC(entry) -> si dice al linker di rilocare l'etichetta entry, che avrà indirizzo fisico 10000C
.globl entry
entry:
movw $0x1234,0x472 # warm boot
# We haven't set up virtual memory yet, so we're running from
# the physical address the boot loader loaded the kernel at: 1MB
# (plus a few bytes). However, the C code is linked to run at
# KERNBASE+1MB. Hence, we set up a trivial page directory that
# translates virtual addresses [KERNBASE, KERNBASE+4MB) to
# physical addresses [0, 4MB). This 4MB region will be suffice
# until we set up our real page table in mem_init in lab 2.
##################################################
#################
la entry_pgdir è una struttura dati definita nel file entrypgdir.c ed è compilata dal compilatore, quindi è già presente nel sistema!
E' la tabella delle pagine di primo livello, in particolare mappa gli indirizzi virtuali [0,4MB) e [3GB,3GB+4MB) agli indirizzi fisici [0,4MB), infatti come ho già detto il kernel ha indirizzi virtuali sopra i 3GB, ma è stato caricato a 1MB! Come viene costruita tale struttura è trattato ampiamente in alcune videolezioni e richiede un discorso molto ampio che non è possibile fare qui, trattando questo file!
Tale struttura dati possiede indirizzi virtuali, e nel registro CR3 ci vanno solo indirizzi fisici, quindi riloco il suo indirizzo e lo inserisco in CR3
##################################################
#################
movl $(RELOC(entry_pgdir)), %eax
movl %eax, %cr3
# Turn on paging.
movl %cr0, %eax
orl $(CR0_PE|CR0_PG|CR0_WP), %eax -> setta il bit 32 si CR0 a 1 abilitando la paginazione
movl %eax, %cr0
# Now paging is enabled, but we're still running at a low EIP
# (why is this okay?). Jump up above KERNBASE before entering
# C code.
##################################################
##################
Questa è la parte un po' più complicata da capire (e da spiegare!): da questo momento (avendo abilitato la paginazione) OGNI indirizzo è intercettato dalla MMU e interpretato come indirizzo virtuale, tuttavia il nostro EIP è ancora a valori bassi (tanto per intenderci, circa 1MB), tuttavia il kernel è stato compilato con indirizzi virtuali, non ha senso continuare a rilocare etichette e strutture dati! per iniziare a far girare il kernel a indirizzi virtuali bisogna spostare l'EIP a indirizzi virtuali, per questo si mette l'indirizzo di relocated (è indirizzo virtuale!) in EAX e si fa una jmp a tale indirizzo. Così facendo l'EIP ha al suo interno indirizzi virtuali e non c'è più bisogno di rilocare alcunchè.
##################################################
##################
mov $relocated, %eax
jmp *%eax
##################################################
################
Notare che già qui si vede perchè abbiamo dovuto mappare gli indirizzi virtuali da [0,4MB) negli indirizzi fisici [0,4MB), creando di fatto un mapping identità: infatti nel momento in cui si abilita la paginazione l'EIP ha valori bassi, che causerebbe un page fault che non sono ancora in grado di gestire!! Quindi di fatto questo mapping è fatto solo per queste due istruzioni!
##################################################
#################
relocated:
movl $0x0,%ebp # nuke frame pointer
#setta lo stack ad indirizzi virtuali, così facendo la call pusha sullo stack del kernel ad indirizzi virtuali
movl $(bootstacktop),%esp
# now to C code
call i386_init
# Should never get here, but in case we do, just spin.
spin: jmp spin
#Sposta lo stack in indirizzi virtuali
.data
##################################################
#################
# boot stack
##################################################
#################
.p2align PGSHIFT # force page alignment
.globl bootstack
bootstack:
.space KSTKSIZE
.globl bootstacktop
bootstacktop:
|