PREKIDI
-------

(ovaj fajl sadrzi beleske sa predavanja. Za vise informacija
pogledati: Dandamudi strane 825-855, Tanenbaum 404-408).


*) ULOGA PREKIDA

   Osnovna uloga sistema prekida je omogucavanje procesoru da reaguje
   na asinhrone dogadjaje koji zahtevaju hitnu obradu. Ukoliko ovakav
   mehanizam ne bi postojao, procesor bi mogao da opsluzi pristigle
   zahteve tek kada zavrsi program koji trenutno izvrsava. Sistem
   prekida omogucava da se trenutni program prekine (uz cuvanje
   njegovog trenutnog statusa i pozicije u programu), da se opsluzi
   odgovarajuci zahtev, a da se zatim program nastavi tamo gde je
   stao, bez znanja o tome da je uopste bio i prekinut.

   Potreba za prekidom se najcesce manifestuje u sledecim slucajevima:

   -) OPSLUZIVANJE ULAZA I IZLAZA: ulazno izlazni uredjaji omogucavaju
      komunikaciju racunara sa spoljnim svetom (korisnikom, drugim
      racunarima i uredjajima). Samim tim, ovi uredjaji funkcionisu
      potpuno asinhrono u odnosu na procesor (npr. procesor ne moze da
      zna kada ce korisnik pritisnuti neki taster na tastaturi ili
      pomeriti misa). Kada ulazno-izlazni uredjaj zeli da komunicira
      sa procesorom, on to najcesce mora da uradi odmah (kako ne bi
      izgubio informacije koje pristizu iz spoljne sredine i kako bi
      korisniku obezbedio odziv sistema u realnom vremenu). Zbog toga
      je neophodno da se procesor prekine u onome sto trenutno radi i
      da se njegova paznja preusmeri na ulazno-izlazni uredjaj.

   -) REALIZACIJA FUNKCIJA OPERATIVNOG SISTEMA: operativni sistem
      cesto ima potrebu da periodicno obavlja neke aktivnosti. Ove
      aktivnosti mogu da ukljucuju odrzavanje memorije, administraciju
      procesa i rasporedjivanje (deljenje vremena), i sl. Na primer,
      da bi se omogucilo izvrsavanje vise procesa istovremeno na
      racunaru (tzv. multi-tasking), operativni sistem deli vreme na
      kratke intervale (ne obavezno jednake duzine) u kojima dodeljuje
      procesor razlicitim procesima. Na ovaj nacin svi procesi u krug
      dobijaju svoje vreme za izvrsavanje, a korisnik ima utisak da
      svi rade istovremeno. Da bi se ovo obezbedilo, potrebno je
      omoguciti da se proces prekine kada njegov vremenski interval
      istekne.

   -) IMPLEMENTACIJA SISTEMSKIH POZIVA: vecina savremenih procesora
      podrzava dva ili vise nivoa privilegija prilikom izvrsavanja
      programa. Npr. Intel-ovi procesori imaju 4 nivoa privilegija
      (nivoi 0-3). Najvisi nivo privilegija (nivo 0 na Intelovim
      procesorima) dozvoljava pristup svim instrukcijama i registrima
      procesora (ukljucujuci i one koji se obicno koriste u sistemske
      svrhe), dok nizi nivoi privilegija zabranjuju upotrebu nekih
      registara i instrukcija i time sprecavaju pristup odredjenim
      delovima i funkcijama racunarskog sistema. Operativni sistemi
      koriste ovaj hardverski mehanizam kako bi napravili distinkciju
      izmedju koda operativnog sistema i koda aplikativnih programa.
      Kod operativnog sistema se izvrava u tzv. SISTEMSKOM REZIMU (pod
      Linux-om se to zove kernel-space), dok se kod aplikativnih
      programa izvrsava u KORISNICKOM REZIMU (user-space). U
      sistemskom rezimu je moguce pristupiti svim resursima racunara,
      i to se ostvaruje na kontrolisan nacin od strane odgovarajucih
      modula operativnog sistema i drajvera perifernih uredjaja. U
      korisnickom rezimu direktan pristup ovim resursima nije moguc.
      Otuda korisnicke aplikacije na neki nacin moraju da od
      operativnog sistema zahtevaju da u njihovo ime i za njihove
      potrebe obavi odgovarajucu operaciju i obezbedi kontrolisanu
      upotrebu odgovarajucih resursa, vodeci pritom racuna o
      bezbednosti celog sistema. Ovo se ostvaruje putem tzv.
      SISTEMSKIH POZIVA. Sistemski pozivi predstavljaju funkcije
      operativnog sistema koje predstavljaju interfejs sa aplikativnim
      programima. Na primer, na UNIX sistemima postoji sistemski poziv
      open() kojim se otvara fajl na disku, kao i pozivi read() i
      write() za pisanje odnosno citanje iz otvorenog fajla. Medjutim,
      ukoliko bi aplikativni program pozvao sistemski poziv direktno,
      kao sto poziva svoje podprograme, odgovarajuci kod bi se
      izvrsavao u korisnickom rezimu, pa ne bi mogao da pristupi
      potrebnim resursima. Dakle, potrebno je na neki nacin obezbediti
      privremeni prelazak u privilegovani, sistemski rezim dok se
      izvrsava sistemski poziv. Na zalost (ili na srecu), procesori
      tipicno ne dozvoljavaju da se tek tako iz nizeg predje u visi
      nivo privilegija (jer bi to obesmislilo postojanje nivoa
      privilegija). Jedan od nacina na koji se to moze postici je
      izazivanje prekida od strane aplikativnog programa. Dakle,
      aplikativni program u odgovarajuce registre upise redni broj i
      argumente sistemskog poziva, a zatim posebnom instrukcijom
      izazove tzv. softverski prekid (vise o tome dole). Procesori su
      tako dizajnirani da prilikom izazivanja prekida automatski
      prelaze u privilegovan rezim rada. Ovaj prekid se obradjuje tako
      sto se izvrsi odgovarajuci kod zahtevanog sistemskog poziva.
      Nakon toga, procesor se vraca u neprivilegovani rezim (ovo je
      obicno jednostavno uraditi, posebnom instrukcijom).


*) VRSTE PREKIDA

  Prekidi mogu biti:

  -) HARDVERSKI PREKIDI: procesor ima jedan ili vise fizickih
     prikljucaka na koji se moze dovesti signal (ili impuls)
     kojim se izaziva prekid. Hardverski prekidi mogu biti:

     -) MASKIRAJUCI (engl. maskable): kod ovih prekida procesor ima
     mogucnost da privremeno ignorise prekide, tj. da ih ne smatra
     prioritetnim.

     -) NEMASKIRAJUCI PREKIDI (engl. non-maskable): kod ovih prekida
     procesor nema mogucnost da ih ignorise, vec mora da odgovori na
     njih.
    
     Hardverski prekidi se zovu i asinhroni prekidi, jer se mogu
     dogoditi u bilo kom trenutku, bez obzira na stanje programa koji
     se trenutno izvrsava.

     PRIMER: Intelovi procesori imaju dva hardverska prikljucka: NMI
     (non-maskable-interrupts) i INTR (interrupt-request). U registru
     EFLAGS (RFLAGS) postoji IF flag (interrupt-flag). Ukoliko je
     postavljen na 0, tada se prekidi koji dolaze preko INTR
     prikljucka ignorisu. Ukoliko je IF = 1, tada se prekidi preko
     INTR prikljucka ne ignorisu, vec se obradjuju. Sa druge strane,
     prekidi koji se dostavljaju preko NMI prikljucka se ne mogu
     ignorisati (obradjuju se bez obzira na vrednost IF flaga).

  -) SOFTVERSKI PREKIDI: ovi prekidi se izazivaju od strane procesora
     posebnim instrukcijama. Na primer, Intel-ovi procesori imaju
     instrukciju INT <br_prekida> koja izaziva odgovarajuci prekid.
     Softverski prekidi se drugacije nazivaju i sinhroni prekidi, zato
     sto se desavaju onda kada softver to zahteva, u unapred
     predvidjenom trenutku.

  -) IZUZETCI (engl. exceptions): u pitanju su prekidi koji nastaju
     kao rezultat nekih gresaka prilikom izvrsavanja instrukcija. Na
     primer, u slucaju deljenja nulom, instrukcija ne moze vratiti ni
     jedan smislen rezultat, pa je potrebno izazvati prekid koji ce
     taj problem obraditi na nacin koji je predvidjen. Izuzetci mogu
     biti razlicitog stepena ozbiljnosti, u zavisnosti od vrste greske
     koja je nastala. Na primer, na Intel-ovim procesorima, izuzetci
     se klasifikuju u tri kategorije:

     -) GRESKE (engl. faults): u pitanju su greske koje su otklonjive,
        pri cemu se pre pozivanja procedure za obradu izuzetka stanje
        programa (registri, programski brojac, i sl.) vraca na ono
        stanje koje je bilo pre pozivanja instrukcije koja je izazvala
        izuzetak. Ovo znaci da ce nakon obrade izuzetka program biti
        nastavljen ponavljanjem sporne instrukcije (pri cemu se
        pretpostavlja da je problem u medjuvremenu otklonjen). Tipican
        primer ovakve greske je kada instrukcija pokusa da pristupi
        podatku koji se ne nalazi u memoriji, jer je privremeno
        izmesten na disk (tzv. virtuelna memorija). Tada ce procedura
        za obradu prekida ucitati odgovarajucu stranicu virtuelne
        memorije sa diska u RAM, nakon cega ce kontrola biti vracena
        programu koji ce ponovo pokusati da izvrsi istu instrukciju.
        Drugi primer je pokusaj izvrsavanja privilegovane instrukcije
        u neprivilegovanom rezimu, zatim deljenje nulom, i sl. 

     -) ZAMKE (engl. traps): u pitanju su greske koje su otklonjive,
        ali se prilikom pozivanja procedure za obradu izuzetka
        zadrzava stanje koje je nastalo nakon izvrsenja sporne
        instrukcije. Primer ovakvih izuzetaka je prekoracenje (INTO
        instrukcija koja proverava OF flag i izaziva izuzetak ako je
        OF=1).
	
     -) ZAUSTAVLJANJA (engl. aborts): javljaju se kada dodje do neke
        neotklonjive greske, kada je jedino smisleno prekinuti
        program. Primeri ovakvih gresaka su hardverske neispravnosti,
        nekonzistentne vrednosti u sistemskim tablicama, i sl. U
        takvim situacijama procedura za obradu prekida cesto i ne zna
        tacno kod koje instrukcije je problem nastao, pa ne moze da
        omoguci resavanje problema i nastavljanje programa tamo gde je
        stao.
	
*) OBRADA PREKIDA

   Kada se javi prekid, potrebno je da procesor zna koja vrsta prekida
   je nastupila, kao i koji je uzrok prekida. Postoje dva nacina da se
   ovo postigne:

   -) ISPITIVANJE PREKIDA (engl. polled interrupts): uredjaj pre nego
      sto izazove prekid u svom statusnom registru postavi
      odgovarajuci bit. Kada procesoru stigne signal za prekid, on
      poziva jedinstvenu proceduru za obradu prekida koja prolazi kroz
      sve uredjaje, ocitava njihove statusne registre i pronalazi
      uredjaj koji je izazvao prekid, a zatim obradjuje prekid na
      odgovarajuci nacin. Nedostatak ovog pristupa je sporost.

   -) NAVODJENJE UZROKA PREKIDA: slicno kao i malopre, s tim sto
      uredjaj koji izaziva prekid smesta informaciju o uzroku i vrsti
      prekida u poseban deljeni registar (koji se obicno nalazi u
      memorijskom prostoru procesora ili u specijalizovanom
      koprocesoru za obradu prekida). Kada uredjaj signalizira prekid,
      procesor poziva jedinstvenu proceduru za obradu prekida koja
      ocitava ovaj registar i na osnovu toga obradjuje prekid na
      odgovarajuci nacin. Ovakav pristup koristi npr. MIPS
      arhitektura.

   -) VEKTORSKI PREKIDI: kod ovog pristupa, svaki tip prekida ima svoj
      redni broj koji nazivamo VEKTOR PREKIDA. Prilikom izazivanja
      prekida, uredjaj na magistralu podataka postavlja ovaj vektor i
      na taj nacin ga dostavlja procesoru. Sa druge strane, procesor
      odrzava u memoriji TABELU DESKRIPTORA PREKIDA (engl. interrupt
      descriptor table, IDT). Ova tabela za svaki od vektora prekida
      sadrzi po jedno polje koje izmedju ostalog sadrzi i adresu
      procedure za obradu tog tipa prekida (dakle, svaki tip prekida
      ima sopstvenu proceduru za obradu).  Vektor prekida se koristi
      kao indeks u ovoj tabeli, preko koje se pristupa proceduri i
      obradjuje prekid. Ovaj pristup se koristi kod Intel-ovih
      procesora.

   PRIMER: Intel-ovi 32-bitni procesori imaju specijalni interni
   registar koji se zove IDTR. U pitanju je 48-bitni registar. Visih
   32 bita ovog registra sadrze adresu IDT tabele u memoriji, dok
   nizih 16 bitova sadrze velicinu ove tabele (izrazenu u
   bajtovima). Vrednost ovog registra postavlja se LIDT instrukcijom
   (ova instrukcija se moze pokrenuti samo u privilegovanom rezimu 0,
   i tipicno je pokrece operativni sistem prilikom
   inicijalizacije). Svaka stavka u IDT tabeli je velicine 8 bajtova i
   predstavlja jedan DESKRIPTOR PREKIDA. Deskriptor sadrzi 32-bitnu
   adresu procedure za obradu prekida, identifikator segmenta, broj
   nivoa privilegija pod kojim ce se procedura za obradu izvrsavati,
   da li procedura za obradu prekida postoji ili ne, i sl.

   Kod 64-bitnih (x86-64) procesora situacija je slicna, s tim sto je
   sada IDTR registar velicine 80-bitova (64 bita za adresu tabele i
   16 bitova za njenu velicinu). Svaki deskriptor u tabeli je sada
   velicine 16 bajtova (kako bi mogao da sadrzi 64-bitnu adresu
   procedure za obradu prekida).

   Vektor prekida na Intel-ovim procesorima je 8-bitni, sto znaci da
   mozemo imati do 256 razlicitih tipova prekida. Prekidi sa brojevima
   od 0 do 31 su rezervisani za izuzetke, kao i za nemaskirajuce
   prekide (vektor broj 2). Prekidi od 32-255 su slobodni za
   koriscenje prilikom maskirajucih hardverskih prekida, kao i za
   softverske prekide.

   Prilikom izuzetka, automatski se pokrece procedura za obradu
   prekida sa odgovarajucim vektorom (npr. pristup privilegovanoj
   instrukciji u neprivilegovanom rezimu rada izazvace izuzetak sa
   prekidnim vektorom 13). Na operativnom sistemu je da obezbedi
   procedure koje ce ove izuzetke obraditi na odgovarajuci nacin.

   Prilikom hardverskog (maskirajuceg) prekida, uredjaj najpre
   ukljucuje signal za prekid preko INTR prikljucka procesora. Kada
   procesor sacuva stanje programa koji se izvrsava, salje uredjaju
   signal INTA (interrupt-acknowledge). Nakon toga uredjaj preko
   magistrale podataka (nizih 8 bitova) dostavlja vektor prekida. Koji
   ce broj odgovarati kom uredjaju, zavisi od toga kako je podesen
   hardver u koji se procesor ugradjuje.

   Prilikom softverskog prekida, operand INT instrukcije predstavlja
   broj prekida. Na primer, za sistemske pozive se pod Linux-om
   koristi prekid broj 128 (0x80 heksadekadno).

   Bez obzira na to kako je prekid nastao, postupak obrade prekida je
   uvek isti:

   1) Prelazi se u odgovarajuci rezim privilegije
   
   2) Vrednost programskog brojaca i statusnog registra procesora se
      cuvaju u memoriji (na steku).

   3) Vektor prekida se koristi kao indeks u tabeli prekida, kako bi
      se odredila i pozvala procedura za obradu prekida

   Procedura za obradu prekida najcesce mora da sacuva sve ostale
   registre procesora koje namerava da koristi, kako bi mogla kasnije
   da ih vrati na stare vrednosti (kako bi program kada/ako nastavi sa
   radom imao neizmenjene vrednosti registara). Na kraju izvrsavanja,
   procedura za obradu prekida poziva IRET instrukciju koja sa steka
   skida i vraca sacuvane vrednosti u statusni registar i programski
   brojac, cime se restauira stanje procesora i nastavlja se sa
   izvrsenjem programa tamo gde je stao.

*) KONTROLERI PREKIDA

   U slucaju da vise uredjaja zeli istovremeno da privuce paznju
   procesora, potrebno je na neki nacin omoguciti da se istovremeno
   signalizira vise prekida, kao i da se na neki nacin odrede
   prioriteti pri obradi prekida. Jedan nacin je da sam procesor ima
   vise linija za prekide, a da se logika za odredjivanje prioriteta
   nalazi unutar procesora. Drugi, fleksibilniji nacin je da postoji
   poseban uredjaj, koji nazivamo KONTROLER PREKIDA. Sada se uredjaji
   koji zele da izazovu prekide povezuju na kontroler prekida, koji
   odredjuje prioritete medju njima, signalizira procesoru da je do
   prekida doslo i salje mu (putem magistrale podataka) vektor prekida
   koji odgovara uredjaju koji je izazvao prekid. Kontroleri prekida
   su najcesce programabilni, tj. omogucavaju softversko podesavanje
   prioriteta uredjaja, brojeva vektora prekida koji odgovaraju
   razlicitim uredjajima, i sl.

   PRIMER: Na Intel-ovim platformama dugo je (od kraja 70-tih pa sve
   do 90-tih) standard predstavljao kontroler PIC 8259
   (programmable-interrupt-controler). Ovaj kontroler je imao 8
   ulaznih linija (IR0-IR7) na koje su se mogli povezivati uredjaji.
   Kada neki uredjaj zeli da izazove prekid, on kontroleru putem svoje
   ulazne linije posalje signal. Kontroler je imao INTR izlaz (koji se
   povezivao na INTR ulaz procesora) kao i INTA ulaz (koji se
   povezivao na INTA prikljucak procesora). Takodje, imao je 8-bitni
   ulaz/izlaz D0-D7 koji se povezivao na nizih 8 bitova magistrale
   podataka. Putem linija D0-D7 je bilo moguce slati vektor prekida
   procesoru, a takodje je putem tih linija bilo moguce programirati
   kontroler (slanjem odgovarajucih komandi koje on razume).

   Interno, kontroler je imao tri 8-bitna registra:

   -) Interrupt Mask Register (IMR): pomocu ovog registra bilo je
      moguce maskirati pojedinacne IR ulaze, i spreciti izuzetke
      sa pojedinacnih uredjaja.

   -) Interrupt Request Register (IRR): njegovi bitovi su oznacavali
      uredjaje koji su trazili prekid i koji cekaju da budu opsluzeni.

   -) In-Service Register (ISR): registar sadrzi masku bitova uredjaja
      za koje je zapoceta obrada prekida (tj. poslat je vektor
      prekida), ali jos uvek nije zavrsena. Kada se obrada prekida
      zavrsi, procedura za obradu prekida pre IRET instrukcije mora
      kontroleru prekida poslati vrednost 0x20 preko magistrale
      podataka (tzv. EOI end-of-interrupt signal), cime se oznacava da
      je obrada prekida zavrsena, te da kontroler moze da signalizira
      novi prekid (ukoliko jos neki od uredjaja ceka da bude
      opsluzen).
 
   Programiranje kontrolera se vrsi prilikom inicijalizacije, kada mu
   se putem magistrale podataka salju odgovarajuce 8-bitne reci kojima
   se podesavaju prioriteti (podrazumevano IR0 ima najvisi, a IR7
   najnizi prioritet), kao i broj vektora prekida za IR0 (ostali su
   onda automatski +1, +2, ..., +7).

   Za potrebe citanja i pisanja iz kontrolera, isti se mora ugraditi u
   adresni prostor procesora. U tu svrhu, postoji CS ulaz
   (chip-select, tj. enable), kao i RD i WR ulazi (za izbor
   operacije). Tradicionalno, kontroler je fizicki mapiran na adresu
   0x20 u adresnom prostoru (tj. za tu adresu se ukljucuje CS ulaz).
   Takodje, postoji i ulaz A0 koji se povezuje na najnizu adresnu
   liniju, i koji sluzi za dodatnu fleksibilnost pri izdavanju komandi
   (efektivno, A0 se ukljucuje kada umesto adrese 0x20 koristimo
   adresu 0x21). 
  
   Tradicionalno, na ulaz IR0 se povezivao tajmer koji je programiran
   da periodicno izaziva prekid, u svrhu preuzimanja kontrole od
   strane operativnog sistema radi implementacije rasporedjivanja
   procesa i deljenja vremena.

   U slucaju da zelimo vise od 8 uredjaja, PIC 8259 je omogucavao da
   se kaskadno povezuje vise ovakvih uredjaja. Bilo je moguce imati
   jedan glavni PIC 8259 (master) i do osam potcinjenih (slave) PIC
   8259 kontrolera. Potcinjeni kontroleri svoje INTR izlaze povezuju
   na IR ulaze glavnog kontrolera. Na ovaj nacin, maksimalni broj
   uredjaja koji su se mogli povezivali na ovakav sistem je bio 64,
   mada je u praksi najcesce bilo manje, jer obicno nije bilo 8
   podcinjenih kontrolera, vec jedan ili dva. Kada neki uredjaj zeli
   prekid, on signalizira svom podcinjenom kontroleru, a ovaj taj
   zahtev prosledi master kontroleru. Master kontroler posalje signal
   procesoru. Kada procesor odgovori (preko INTA), tada glavni
   kontroler salje komandu (putem posebnih CAS0, CAS1, CAS2
   ulaza/izlaza) odgovarajucem podcinjenom kontroleru cime mu nalaze
   da na magistralu podataka postavi vektor prekida [svi kontroleri su
   povezani na istu magistralu podataka]. Prilikom programiranja ovako
   organizovanog sistema, potrebno je da svaki od PIC 8259 uredjaja
   ima drugacije podesene vektore prekida, kako ne bi bilo konflikta
   medju uredjajima. Za programiranje PIC 8259 uredjaja zaduzen je
   BIOS (neka od ovih podesavanja su bila dostupna i korisniku iz
   BIOS-a, kako bi mogao da podesi odgovarajuce prekidne vektore).

   U novije vreme se umesto PIC 8259 cipa koristi tzv. APIC sistem
   (Advanced Programmable Interrupt Controler). Glavna prednost ovog
   sistema je u tome sto je fleksibilniji i omogucava vise
   podesavanja. Takodje, omogucava slanje i distribuciju prekida
   izmedju vise procesora, sto je od znacaja za viseprocesorske
   sisteme. Sistem se sastoji iz tzv lokalnog APIC-a (LAPIC) i ulazno
   izlaznog APIC-a (I/O APIC). LAPIC se nalazi na samom procesoru
   (dakle, svaki procesor ima svoj LAPIC). I/O APIC je najcesce
   jedinstven i nalazi se negde na ploci (tipicno u okviru juznog
   mosta ili PCH cipa). Na I/O APIC se tipicno mogu povezati 24 (u
   novije vreme i vise) razlicita uredjaja. Komunikacija izmedju
   LAPIC-a i I/O APIC-a se ostvaruje putem sistemskih magistrala. I/O
   APIC se moze programirati tako da odgovarajuce prekidne vektore
   salje odgovarajucim LAPIC uredjajima, u zavisnosti od toga kom je
   procesoru namenjen taj prekid. LAPIC je zaduzen za prikupljanje
   svih prekida koji stizu tom procesoru, odredjivanje prioriteta i
   isporuku procesoru (putem INTR i NMI prikljucaka). Takodje, LAPIC
   moze slati prekidne signale drugim LAPIC uredjajima. Najzad, vecina
   LAPIC uredjaja u sebi sadrze ugradjen tajmer koji se moze
   fleksibilnije podesavati, sto omogucava efikasniju implementaciju
   algoritma rasporedjivanja kod operativnih sistema.
   
   
     
     
