V tomto cvičení preskúmate tabuľky stránok a upravíte ich za účelom zrýchlenia určitých systémových volaní a detekcie stránok, ku ktorým proces pristúpil.
Než začnete programovať, prečítajte si kapitolu 3 xv6 knižky a pozrite si príslušné súbory:
Nápomocný môže byť tiež manuál privilegovaných inštrukcií RISC-V.
Od tohto cvičenia môžete pracovať na vlastných laptopoch. Predpokladáme, že ste si na nich už nastavili synchronizáciu s vaším vzdialených repozitárom na GitHube podľa sekcie Stiahnutie repozitára na vlastný PC na stránke Synchronizácia repozitára. Ak chcete pracovať s počítačmi v miestnosti, postupujte podľa sekcie Stiahnutie repozitára na cvičení.
Najprv sa prepnite do vetvy pgtbl:
1 2 3 |
$ git fetch $ git switch pgtbl $ make clean |
Riešenia úloh z tohto cvičenia ukladajte do vetvy pgtbl.
Niektoré operačné systémy (napr. Linux) zrýchľujú určité systémové volania zdieľaním dát medzi jadrom a užívateľským priestorom v pamäťovej oblasti s prístupom iba na čítanie. Vďaka tomu je možné eliminovať prechody do jadra počas systémových volaní. Aby ste sa naučili, ako fungujú pamäťové mapovania, vašou prvou úlohou je implementovať túto optimizáciu pre systémové volaniegetpid()
v xv6.
USYSCALL
(táto virtuálna adresa je definovaná v súbore memlayout.h). Na začiatku tejto stránky uložte štruktúru struct usyscall
(tiež definovaná v memlayout.h) a inicializujte ju tak, aby v nej bolo uložené PID aktuálneho procesu. Pre tento lab je z užívateľského priestoru k dispozícii funkcia ugetpid()
, ktorá automaticky použije mapovanie USYSCALL
. Za implementáciu tejto úlohy získate plný počet bodov, ak prejdete testom ugetpid v súbore testov pgtbltest.Pomôcky:
allocproc()
. Vhodné je tiež niekam uložiť referenciu na alokovanú stránku, napríklad do štruktúry proc
, podobne ako sa ukladá proc->trapframe
a proc->pagetable
.proc_pagetable()
v súbore kernel/proc.c.
mappages()
sa vám môže hodiť.
freeproc()
a odmapovať v proc_freepagetable()
.
Ktoré iné systémové volania môžu byť urýchlené prostredníctvom tejto zdieľanej stránky? Vysvetlite ako.
Odpovede zapíšte do príslušných súborov podľa testovacieho skriptu.
Po úspešnom dokončení úlohy nezabudnite vytvoriť commit!
Vašou druhou úohou je napísať funkciu, ktorá vypíše obsah tabuľky stránok. Pomôže vám to pri vizualizícii tabuliek stránok v RISC-V a funkciu môžete v budúcnosti použiť pri ladení systému.
vmprint()
. Bude mať jeden argument typu pagetable_t
a vypíše tabuľku stránok vo formáte, ktorý je uvedený nižšie. Funkciu môžete otestovať napríkad tak, že ju zavoláte v súbore exec.c tesne pred return argc
. Aby bola tabuľka vypísaná len pre prvý proces, skontrolujte číso procesu: if(p->pid==1) vmprint(p->pagetable)
. Plný počet bodov za túto úlohu dostanete, ak prejdete testom pte printout.
Keď spustíte xv6, mali by ste vidieť podobný výstup. Ak ste funkciu zavolali vyššie popísaným spôsobom, jedná sa o stav tabuľky prvého procesu (init) tesne pred jeho spustením v systémovom volaní exec
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
page table 0x0000000087f6b000 ..0: pte 0x0000000021fd9c01 pa 0x0000000087f67000 .. ..0: pte 0x0000000021fd9801 pa 0x0000000087f66000 .. .. ..0: pte 0x0000000021fda01b pa 0x0000000087f68000 .. .. ..1: pte 0x0000000021fd9417 pa 0x0000000087f65000 .. .. ..2: pte 0x0000000021fd9007 pa 0x0000000087f64000 .. .. ..3: pte 0x0000000021fd8c17 pa 0x0000000087f63000 ..255: pte 0x0000000021fda801 pa 0x0000000087f6a000 .. ..511: pte 0x0000000021fda401 pa 0x0000000087f69000 .. .. ..509: pte 0x0000000021fdcc13 pa 0x0000000087f73000 .. .. ..510: pte 0x0000000021fdd007 pa 0x0000000087f74000 .. .. ..511: pte 0x0000000020001c0b pa 0x0000000080007000 init: starting sh |
V prvom riadku je argument funkcie vmprint
. Potom nasledujú riadky pre každý PTE, vrátane vnorených záznamov. Každý riadok PTE je odsadený znakmi ..
podľa toho, ako hboko v strome sa nachádza. Každý riadok obsahuje index záznamu, bity pte
a fyzickú adresu vytiahnutú z PTE. Nevypisujte neplatné záznamy. V príklade vyššie má tabuľka najvyššej úrovne mapovania pre záznamy 0 a 255. O úroveň nižšie, záznam 0 má namapovaný len index 0. Na najnižšej úrovni má tento index namapované záznamy 0, 1, 2 a 3.
Fyzické adresy na vašom počítači môžu byť odlišné od tých v ukážke výstupu. Počet záznamov a virtuálne adresy by mali byť rovnaké.
Pomôcky:
vmprint()
môžete definovať v kernel/vm.c.
freewalk()
.
vmprint()
dajte do kernel/defs.h, aby ste ju mohi zavolať z exec.c.
%p
na výpis PTE a adries ako 64-bitové hexadecimálne číslo.Vysvetlite logický význam každej dátovej stránky, ktorú vypísala funkcia vmprint()
. Ku každej takej stránke tiež uveďte jej prístupové bity. Pomôžte si obrázkom 3.4 z xv6 knižky. Tento obrázok ale nemusí presne reprezentovať proces init, ktorého adresný priestor skúmame.
Odpovede zapíšte do príslušných súborov podľa testovacieho skriptu.
Niektorým garbage collectorom (forma automatickej správy pamäte) môže byť užitočná informácia o tom, ku ktorým stránkam bol v minulosti uskutočnený prístup (čítanie alebo zápis). V tejto časti cvičenia budete implementovať do xv6 novú funkcionalitu, ktorá deteguje a ohlási túto informáciu užívateľskému priestoru preskúmaním prístupových bitov v tabuľke stránok architektúry RISC-V. Hardvér tejto architektúry nastavuje tieto bity v PTE vždy, keď fyzickú adresu stránky nenájde v TLB cache.
pgaccess()
, ktoré oznámi stránky, ku ktorým bol v minulosti vykonaný prístup. Toto systémové volanie má tri argumenty. Prvý je virtuálna adresa začiatku stránky, ktorú má prvú skontrolovať. Druhý je počet stránok, ktoré má skontrolovať. Tretí je užívateľská adresa pamäte, kde bude výsledok zapísaný vo forme bitovej masky (dátová štruktúra, ktorá používa jeden bit na stránku a prvú stránku reprezentuje najmenej významný bit). Za túto úlohu dostanete plný počet bodov, ak prejdete testom pgaccess v súbore testov pgtbltest.
Pomôcky:
pgaccess_test()
v súbore user/pgtbltest.c, aby ste videli, ako sa volanie pgaccess
používa.sys_pgaccess()
v súbore kernel/sysproc.c.
argaddr()
a argint()
.
copyout()
) potom, ako ho naplníte správnymi bitmi. Nezabudnite skopírovať len toľko dát, koľko si užívateľ vyžiadal (zaokrúhlené na bajty).
walk()
v súbore kernel/vm.c je veľmi užitočná na hľadanie správnych PTE.
PTE_A
musíte definovať v súbore kernel/riscv.h. Nahliadnite do tretej kapitoly xv6 knižky, aby ste zistili jeho hodnotu. Môžete použiť tiež manuál privilegovaných inštrukcií RISC-V.
PTE_A
ju nezabudnite vynulovať, ak bola nastavená. V opačnom prípade nebudete vedieť zistiť, či bolo k stránke pristúpené od posledného volania pgaccess()
(inými slovami, bit bude navždy nastavený).
vmprint()
sa vám môže hodiť pri ladení.
Po úspešnom dokončení úlohy nezabudnite vytvoriť commit!
Týmto je cvičenie hotové. Skontrolujte, či vaše riešenie prejde všetkými testami make grade. Aby ste prešli posledným testom time, musíte vytvoriť nový súbor time.txt, v ktorom uvediete počet hodín, ktorý ste strávili nad zadaním ako celé číslo. Na záver nezabudnite aj túto zmenu commitnúť do repozitára.
make grade môže zlyhať aj v prípade, že testy osamote zbehnú v poriadku. Je to spôsobené časovým limitom testov. Môžete ho zvýšiť v príslušnom súbore grade-lab-pgtbl (parametre timeout
). Časový limit zmeňte iba v takom prípade, že viete, že samotný test zbehne v poriadku a nič iné v súbore neupravujte.
Pre úspešné testovanie je potrebné použiť aspoň 3 jadrá vo VirtualBoxe.
Prvý riešiteľ každej úlohy môže dostať bonusové body po kontrole riešenia. Informujte sa u prednášajúceho alebo cvičiaceho. Voliteľné úlohy môžete riešiť až po vyriešení všetkých úloh základnej časti cvičenia! Riešenia prijímame iba do konca štvrtého týždňa semestra.
PTE_D
.