G. Frosini Interruzioni Slide 1

Slides:



Advertisements
Presentazioni simili
Gestione dei dispositivi di I/O:
Advertisements

Sistemi Elettronici Programmabili
Script bash I file di comandi in Linux. BASH  Bourne Again Shell  Modalità interattiva o batch (file di comandi)  Ambiente di programmazione “completo”
LA MEMORIA CENTRALE. La memoria nella struttura generale del calcolatore MEMORIA CONTROLLO INGRESSO E USCITA ARITMETICA E LOGICA CPU Dispositivi esterni.
IL PROCESSORE I MICROPROCESSORI INTEL Il microprocessore è un circuito integrato dotato di una struttura circuitale in grado di effettuare un determinato.
Fondamenti di Informatica - D. Talia - UNICAL 1 Fondamenti di Informatica FONDAMENTI DI INFORMATICA Domenico Talia
1 Elementi DI INFORMATICA Università degli Studi di Cagliari Corso di Laurea in Ingegneria Elettronica Linguaggio C A.A. 2011/2012
Sistemi Operativi : Gestione della Memoria Anno Scolastico 2012/2013 Un sistema operativo è un programma o un insieme di programmi che garantisce e permette.
Laboratorio di Architettura Degli Elaboratori1 PSPICE – Circuiti sequenziali.
IL SISTEMA OPERATIVO (seconda parte) PROGRAMMI UTENTE INTERPRETE COMANDI FILE SYSTEM GESTIONE DELLE PERIFERICHE GESTIONE DELLA MEMORIA GESTIONE DEI PROCESSI.
13 gennaio Sistema di rilevazione delle temperature all’interno di Personal Computer Industriali Dipartimento di Ingegneria Elettronica SISTEMA.
Elementi fondamentali dell’ Architettura di di un elaboratore elettronico.
Informatica - CDL in Scienze Politiche e delle Relazioni Internazionali A.A Architettura di un calcolatore Ing. Simona Colucci.
.  I tipi di dati non primitivi sono gli array, le struct e le union.  Gli array sono degli aggregati di variabili dello stesso tipo.  La dichiarazione.
CONTROLLO DELLA CONCORRENZA
IL SOFTWARE (FPwin 6.0).
© 2007 SEI-Società Editrice Internazionale, Apogeo
Algoritmi Avanzati a.a.2014/2015 Prof.ssa Rossella Petreschi
Architettura e funzionalità
G. Frosini Memoria virtuale Slide 1
I PROCESSI.
BUS PCI G. Frosini Bus PCI Slide 1.
G. Frosini Elaboratore 32 PC Slide 1
Introduzione al linguaggio C
G. Frosini – Multiprogrammazione e Protezione Slide 1
G. Frosini – Programmazione mista Slide 1
Sistema di Analisi e di Acquisizione
LE ARCHITETTURE NON VON NEUMANN
Protocollo di locking a due fasi stretto
Microcontrollori e microprocessori
I microprocessori Il microprocessore è un circuito integrato costituito da silicio. Il microprocessore svolge fondamentalmente due funzioni: sovraintende.
IL CONCETTO DI ALGORITMO
10. Programmazione Ricorsiva Ing. Simona Colucci
Cammino dei Dati (Datapath)
DMA (BUS MASTERING PCI)
CALCOLATORI ELETTRONICI Anno Accademico
Excel 1 - Introduzione.
CORRISPONDENZA C++ ASSEMBLER
G. Frosini – Ingresso e uscita Slide 1
Organizzazione fisica
I FILES AD ACCESSO SEQUENZIALE
Introduzione I microcontrollori.
I BUS È un insieme di fili conduttori che permette il passaggio di dati tra le varie periferiche del pc.
Tipo di dato: array Un array è un tipo di dato usato per memorizzare una collezione di variabili dello stesso tipo. Per memorizzare una collezione di 7.
SAS® OnDemand for Academics SAS Studio
analizzatore di protocollo
G. Frosini - Programmi di sviluppo Slide 1
ALU (Arithmetic Logic Unit)
istalliamo l’ambiente di sviluppo - ide
Introduzione L’8254 è un interval timer event/counter, progettato per risolvere i problemi del controllo del timing, comuni ad ogni microcomputer. E’ costituito.
Programmazione e Laboratorio di Programmazione
Processi e Thread Meccanismi di IPC (1).
Programmazione e Laboratorio di Programmazione
Ricorsione 16/01/2019 package.
Sviluppo di un programma
Definizione di linguaggio di programmazione
File System ed Input/Output
LINUX: struttura generale
La struttura dei primi programma in C
Parti interne del computer
Programmazione e Laboratorio di Programmazione
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C
Programmazione e Laboratorio di Programmazione
Unità 1 Programmi base.
Lezione Terza Primi passi di programmazione
Programmazione e Laboratorio di Programmazione
Array e Stringhe Linguaggio C.
Progetto del processore e supporto del processore al SO (interruzioni – eccezioni) Salvatore Orlando.
Macchina a stati finiti DMAC
Programmazione e Laboratorio di Programmazione
Transcript della presentazione:

G. Frosini Interruzioni Slide 1

Concetto di Interruzione sospensione forzata del programma in esecuzione; trasferimento del controllo ad un'apposita routine di servizio. Routine di servizio: soddisfa le esigenze che hanno provocato l'interruzione e, al termine, restituisce il controllo al programma sospeso. G. Frosini Interruzioni Slide 2

G. Frosini Interruzioni Slide 3 Fonti di Interruzione Interruzioni esterne: determinate da richieste sul piedino /INTR (INTerrupt Request) o sul piedino /NMI (Non Maskable Interrupt); richieste su /NMI: si traduce in una interruzione (interruzione non mascherabile); richieste su /INTR: si traduce o meno in una interruzione a seconda che il flag IF (Interrupt Flag: bit n. 9 del registro EFLAG) valga 1 oppure 0 (interruzione mascherabile). Interruzioni software: prodotte da un’istruzione INT. Single Step Trap: prodotte, al termine della fase di esecuzione di ogni istruzione, se il flag TF (Trap Flag: bit n. 8 del registro EFLAG) vale 1: fa eccezione l'istruzione che ha provveduto a porre ad 1 il flag TF. Eccezioni nel processore: prodotte da circuiterie di controllo interne al processore, al verificarsi di una condizione anomala che impedisce il completamento della istruzione in corso. G. Frosini Interruzioni Slide 3

Richieste e Interruzioni Richieste di interruzione esterne: possono giungere al processore in qualunque momento (sono asincrone rispetto al programma); il processore porta a termine l'esecuzione dell'istruzione in corso, ed esamina le richieste prima di effettuare il prelievo dell’istruzione successiva; un’interruzione esterna non può sospendere nel bel mezzo l'esecuzione di una istruzione. Altre richieste di interruzione: sono prodotte dalla esecuzione di istruzioni (sono sincrone rispetto al programma); interruzioni software e per single step trap: avvengono alla fine della fase di esecuzione e non producono nessuna sospensione di istruzione; eccezioni: sospendono l'esecuzione dell’istruzione che ha prodotto l'anomalia. G. Frosini Interruzioni Slide 4

Tipo di una interruzione Ogni interruzione ha associato un tipo: il tipo determina l'indirizzo della routine di servizio; i tipi possibili sono 256, ed altrettanti le possibili routine di servizio. Regola per ricavare il tipo. Interruzioni esterne: richiesta sul piedino /NMI: tipo implicito (2); richiesta sul piedino /INTR: tipo prelevato da un apposito bus (bus di interruzione), che collega il processore con il controllore di interruzione APIC) (l'invio di una richiesta su questo piedino deve essere accompagnato dalla specifica del tipo). Interruzioni software: tipo dato dall'operando immediato (ad 8 bit) dell'istruzione INT (è compito del programmatore specificare il tipo). Single Step Trap: tipo implicito (1). Eccezioni nel processore: tipo implicito e legato alla causa che determina l'interruzione. G. Frosini Interruzioni Slide 5

G. Frosini Interruzioni Slide 6 Eccezioni Suddivisione delle eccezioni: trap: avviene alla fine dell’esecuzione di un’istruzione; fault: errore recuperabile, che avviene mentre viene eseguita un’istruzione; abort: errore irrecuperabile, che produce la terminazione forzata dell’istruzione: viene tipicamente utilizzata per segnalare errori hardware. Esempi di eccezioni Tipo Causa dell’interruzione 0 Quoziente non rappresentabile durante l'esecuzione delle istruzioni DIV, IDIV (fault) 4 Presenza di overflow durante l'esecuzione dell'istruzione INTO (trap) 5 Superamento dei limiti durante l'esecuzione dell'istruzione BOUND (fault) 6 Codice operativo non valido (fault) 16 Errore nella unità FPU (fault) G. Frosini Interruzioni Slide 6

G. Frosini Interruzioni Slide 7 Tabella IDT Processore PC: in memoria, a partire da un indirizzo contenuto in un registro del processore (IDTR), è presente la Tabella delle Interruzioni (IDT: Interrupt Descriptor Table); la tabella IDT contiene tanti descrittori quanti sono i tipi (256); ogni descrittore (cancello o gate) è costituito da 8 byte. Cancello: specifica l'indirizzo della routine di servizio dell'interruzione; possiede un byte di accesso, nel quale compaiono i bit P e TI. G. Frosini Interruzioni Slide 7

Azioni del processore per una interruzione Il processore, quando accetta una richiesta di interruzione, compie le seguenti azioni: riconosce il tipo dell'interruzione; preleva da un cancello (a partire dall'indirizzo, relativo alla tabella, dato da tipo*8) il nuovo indirizzo e il byte di accesso; se il bit P del byte di accesso vale 0 (cancello non presente), genera una eccezione (fault di tipo implicito 11); immette in pila tre parole lunghe, la prima contenente il valore di EFLAG e la terza il valore di EIP (la seconda contiene informazioni che sono significative per la protezione); carica il nuovo indirizzo in EIP; pone a 0 il flag TF se il bit TI del byte di accesso vale 1 (cancello di trap) (il flag IF non viene modificato), o entrambi i flag TF ed IF se il bit TI vale 0 (cancello di interrupt). G. Frosini Interruzioni Slide 8

G. Frosini Interruzioni Slide 9 Routine di servizio Routine di servizio: inizia dall'indirizzo corrispondente al nuovo valore caricato in EIP. Termine della routine di servizio: ritorno al programma che era stato interrotto; tale ritorno avviene tramite l'esecuzione della istruzione IRET, la quale preleva dalla pila tre parole lunghe, trasferisce la prima in EIP e la terza in EFLAG. Meccanismo vettorizzato: una interruzione ha associato un tipo, che determina l'acceso ad un determinato cancello, e quindi l'esecuzione di una routine dipendente dal tipo. G. Frosini Interruzioni Slide 9

G. Frosini Interruzioni Slide 10 Tipi di cancello Cancelli di interrupt: la routine di servizio viene eseguita con il processore disabilitato ad accettare nuove richieste di interruzioni mascherabili; non si ha annidamento delle interruzioni mascherabili, a meno che la routine di servizio non provveda esplicitamente a porre nuovamente ad 1 il flag IF. Cancelli di entrambi i tipi (di interrupt e di trap): durante l'esecuzione della routine di servizio non si verifica mai il single step trap, a meno che la routine non provveda esplicitamente a porre nuovamente ad 1 il flag TF. G. Frosini Interruzioni Slide 10

Riconoscimento del tipo di interruzione Tipo implicito: interruzioni esterne non mascherabili; single step trap; eccezioni nel processore. Interruzioni software: tipo coincidente con l'operando della istruzione INT. Interruzioni esterne mascherabili: tipo prelevato dal bus di interruzione. G. Frosini Interruzioni Slide 11

G. Frosini Interruzioni Slide 12 Indirizzo di ritorno Interruzioni esterne, software, di single step trap: memorizzazione in pila dell'indirizzo dell’istruzione che deve ancora essere eseguita (quello dell'istruzione sequenzialmente successiva, ovvero quello determinato da un salto). Eccezioni: trap, fault e abort. Trap: come al punto precedente. Fault: memorizzazione in pila dell'indirizzo dell'istruzione che ha prodotto l'eccezione, con conseguente riesecuzione della stessa al termine della routine di servizio (dopo l'esecuzione dell’istruzione IRET). Abort: terminazione forzata della istruzione attuale (non è significativo l'indirizzo della istruzione che deve essere ancora eseguita). G. Frosini Interruzioni Slide 12

G. Frosini Interruzioni Slide 13 Registri fotocopia Per poter rieseguire un’istruzione, i contenuti dei registri del processore non devono venir alterati fino a quando l'istruzione stessa non è terminata. Nel processore sono previsti registri fotocopia: all’inizio della fase di chiamata, il contenuto dei registri originari viene ricopiato nei registri fotocopia (EIP non è ancora stato aggiornato); durante la fase di chiamata, viene aggiornato il valore di EIP fotocopia; nella fase di esecuzione, le micro operazioni avvengono sui registri fotocopia; alla fine della fase di esecuzione, il contenuto dei registri fotocopia viene ricopiato in quelli originari. Se si genera un fault (istruzione non terminata, eventuale scrittura in memoria del risultato non ancora avvenuta): in pila vengono memorizzati i valori dei registri originari EFLAG ed EIP non ancora aggiornati (EIP contiene l’indirizzo dell’istruzione che ha prodotto il fault). G. Frosini Interruzioni Slide 13

G. Frosini Interruzioni Slide 14 Inizializzazione Routine di interruzione: sono in genere fornite con il software di base del sistema; vengono caricate in memoria alla inizializzazione del sistema da un programma di bootstrap; svolgono compiti differenziati, legati alla causa che ha determinato l'interruzione. Programma di bootstrap: provvede anche a riempire la tabella delle interruzioni in modo consistente con gli indirizzi delle routine di servizio caricate. Ulteriore azione del programma di bootstrap: abilitazione delle interruzioni mascherabili. G. Frosini Interruzioni Slide 14

Classificazione delle routine di servizio (1) Interruzioni esterne non mascherabili: prodotte da cause catastrofiche, come l'abbassarsi della tensione di alimentazione sotto un livello di soglia; routine di servizio (unica, essendo unico il tipo): provvede ad effettuare opportune azioni di recupero. Interruzioni esterne mascherabili: prodotte tipicamente dalle interfacce di I/O; routine di servizio (driver): provvedono ad effettuare il trasferimento dei dati. Istruzione INT: invocazione di routine di sistema (primitive), con un meccanismo alternativo alla CALL; riferisce primitive tramite un numero d'ordine e non con un nome: non è necessaria l’operazione di collegamento. Eccezioni: routine di servizio: sostituendosi al programma in esecuzione, impediscono che questo continui ad operare in modo scorretto (possono semplicemente inviare un messaggio di errore). G. Frosini Interruzioni Slide 15

Classificazione delle routine di servizio (2) Single Step Trap: la routine di servizio consente ad un utente, che abbia posto TF ad 1, di eseguire il programma in single step, con esame ed eventualmente modifica, dopo ogni istruzione, del il contenuto dei registri e delle locazioni di memoria e di I/O; la routine gira con il flag TF a 0 (per non essere essa stessa eseguita in single step); la routine memorizza il contenuto dei registri in una apposita area di memoria e gestisce le operazioni di visualizzazione/modifica; prima di terminare, la routine ripristina il contenuto dei registri del processore e (con l’istruzione IRET) il vecchio contenuto del registro EFLAG: in tal modo il flag TF assume nuovamente il valore 1. Nuovo Single Step Trap: si verifica alla fine della successiva istruzione del programma utente (non dopo l'istruzione IRET, in quanto questa ha provveduto a mettere ad 1 il flag TF). G. Frosini Interruzioni Slide 16

Struttura di una primitiva (1) .data ... .text … main: ... int $TIPO_i rit: … xorl %eax, %eax ret #*********************************************************************** primitiva_j: # routine TIPO_i pushal # istruzione che puo’ essere omessa parte elaborativa della routine popal # istruzione che puo’ essere omessa iret G. Frosini Interruzioni Slide 17

Struttura di una primitiva (2) Salvataggio e ripristino del contenuto dei registri utilizzati: in una primitiva questa azione viene normalmente effettuata; tuttavia, si può anche supporre che il programma principale, al momento della invocazione della primitiva, non lasci nei registri informazioni da conservare. Tipo di gate: mandate in esecuzione tramite gate di tipo interrupt (ipotesi semplificativa); vengono pertanto eseguite con le interruzioni mascherabili disabilitate. G. Frosini Interruzioni Slide 18

G. Frosini Interruzioni Slide 19 Controllore APIC (1) Processore PC: possiede un solo piedino /INTR per le richieste di interruzioni mascherabili. Calcolatore: contiene più sorgenti di interruzione. Controllore di interruzione: circuiteria apposita che gestisce più fonti di interruzione; stabilisce, nel caso di richieste multiple, quale di queste debba avere la precedenza. Caso tipico: circuiteria costituita da un controllore di interruzione APIC (IO APIC + LOCAL APIC); le richieste di interruzione possono essere più di una sullo stesso piedino: in questo caso avviene una operazione di OR se le richieste sono rappresentate da uno 0 logico (OR di collettore). G. Frosini Interruzioni Slide 19

G. Frosini Interruzioni Slide 20 Controllore APIC (2) G. Frosini Interruzioni Slide 20

G. Frosini Interruzioni Slide 21 Controllore APIC (3) Montato nello spazio di memoria. Visibile al programmatore come un insieme di registri a 32 bit: 3 registri direttamente accessibili: IORegSel: 0xFEC00000: porta per gli indirizzi IOWin: 0xFEC00010: porta per i dati EOI: 0xFEE000B0: per la configurazione End Of Interrupt 64 registri speciali, che stabiliscono alcune modalità di funzionamento. Piedini IR23-IR0: servono a ricevere le richieste di interruzione provenienti da sorgenti esterne. Tutto avviene come se: per il collegamento al bus, fosse in possesso dei classici piedini per i dati (D31-D0), per gli indirizzi (A31-A2, /BE3-/BE0), per i comandi di lettura e scrittura e per l'abilitazione (/RD, /WR, /S). per il colloquio con il processore, fosse in possesso di un piedino /INTR, di un piedino /INTA e di un piedino TP collegato ai piedini omonimi del processore. G. Frosini Interruzioni Slide 21

G. Frosini Interruzioni Slide 22 Controllore APIC (4) Tabella interna: costituita da 24 entrate; inizia all’indirizzo interno =16 (0x10); Entrata: associata a un piedino IR; costituita da due registri da 32 bit. Registro di indirizzo minore: 1 bit che maschera (valore 1) le richieste di interruzione (bit 16); 8 bit per il tipo (va da 0x10 a 0xFE) associato alle richieste di interruzione (bit 7-0). 1 bit per la forma del segnale, livello (valore 1) oppure impulso (valore 0) (bit 15); 1 bit per la polarità, attivo basso (valore 1) o attivo alto (valore 0) (bit 13): significato di attivo basso: se livello, valore 0, se impulso sequenza di valori 1-0-1; significato di attivo alto: se livello, valore 1, se impulso sequenza di valori 0-1-0. G. Frosini Interruzioni Slide 22

G. Frosini Interruzioni Slide 23 Controllore APIC (5) Colloquio tra controllore e processore,: previsto un bus speciale (bus di interruzione), che può essere schematizzato come un insieme di 3 collegamenti: /INTR: il controllore invia al processore richieste di interruzione; /INTA: il controllore riceve risposta a una richiesta di interruzione; TP: il controllore invia (serialmente) il tipo di interruzione al processore. Priorità delle richieste: livelli di priorità (16) dipendenti dai 4 bit più significativi del tipo; il controllore, quando accetta una richiesta di interruzione: continua a gestire le richieste a maggiore priorità; cessa di gestire (ma non di memorizzare) le richieste a minore o uguale priorità; tutto ciò fino a quando il controllore stesso non riceve (via software, nel registro EOI) la configurazione End Of Interrupt (valore 0): da quel momento il controllore riprende a gestire anche le richieste di interruzione a minore o uguale priorità rispetto a quella servita (che ha inviato la configurazione End Of Interrupt). G. Frosini Interruzioni Slide 23

G. Frosini Interruzioni Slide 24 Controllore APIC (6) Controllore APIC: funziona in modo annidato (quello precedentemente descritto); utilizza due registri (non visibili al programmatore) IRR (Interrupt Request Register) e ISR (In Service Register), ciascuno di 256 bit (ogni bit associato a uno dei 256 tipi di interruzione). Registri IRR e ISR: suddivisi in 16 parti, a cui corrispondono priorità crescenti da destra a sinistra; ciascuna parte è composta da 16 bit a cui corrisponde la stessa priorità. Tabella interna: associa a ognuno dei piedini IR0-IR23: il bit di maschera; il tipo di interruzione; la forma (impulso o livello) e la polarità del segnale di richiesta di interruzione. Azioni del controllore APIC: le azioni di cui ai successivi punti 1., 2. e 3. sono svolte in parallelo. G. Frosini Interruzioni Slide 24

G. Frosini Interruzioni Slide 25 Controllore APIC (7) Il controllore, ogni volta che riceve una richiesta di interruzione tramite uno dei piedini IR0-IR23, pone a 1 il bit di IRR corrispondente al tipo: per segnali di richiesta aventi la forma di impulso, una richiesta di interruzione è rappresentata da un segnale che da inattivo diviene attivo; per segnali aventi la forma di livello, una richiesta di interruzione è rappresentata da un segnale che risulta attivo nel momento in cui il controllore riceve la configurazione End Of Interrupt. Il controllore ripete ciclicamente i seguenti passi: a) attende che il il bit più significativo di IRR di valore 1 abbia una priorità maggiore del bit più significativo di ISR di valore 1; b) invia al processore una richiesta di interruzione attivando il piedino /INTR; c) attende la risposta sul piedino /INTA e, quando la riceve: i) considera il bit di IRR più a sinistra di valore 1, sia il j-mo; ii) pone a 0 il j-mo bit di IRR e ad 1 il j-mo bit di ISR; iii) invia j (tipo dell’interruzione) al processore (serialmente) sul collegamento TP; iv) rimuove la richiesta di interruzione al processore disattivando il piedino /INTR; Il controllore, ogni volta che riceve (via software) la configurazione End Of Interrupt, azzera il bit più a sinistra di ISR di valore 1 (non possono esservi richieste sotto servizio di uguale priorità, e la routine in esecuzione è certamente quella che gestisce la richiesta sotto servizio a più alta priorità). G. Frosini Interruzioni Slide 25

Driver di interruzione (1) Driver di interruzione con risposta: in genere effettua azioni che rappresentano anche una risposta alla richiesta di interruzione effettuata (semplicemente, legge o scrive in un registro dell’interfaccia); la fonte che ha effettuato una richiesta rimuove la richiesta stessa; il segnale di richiesta è costituito da un livello di polarità bassa (possono esservi più richiedenti per quel piedino). Driver di interruzione senza risposta: non fornisce alcuna risposta all’interfaccia; il segnale di richiesta è costituito da un impulso (il richiedente per quel piedino è unico e la polarità può essere qualsivoglia). Controllore di interruzione: deve essere programmato in modo opportuno per i differenti piedini IR23-IR0. G. Frosini Interruzioni Slide 26

Driver di interruzione (2) … .text driver_j: # routine TIPOj pushal ... parte elaborativa del driver cli # nell’ipotesi che si usa un gate di tipo trap movl $0, 0xFEE000B0 # invio di End Of Interrupt popal iret Configurazione End-Of-Interrupt: vale 0 (su 32 bit). Invio della configurazione End Of Interrupt: interruzioni disabilitate: garantiscono che il driver non venga interrotto da richieste a minore (o uguale) priorità. G. Frosini Interruzioni Slide 27

Driver di interruzione (3) Istruzione IRET: ripristina il vecchio valore del registro EFLAG (che avrà il flag IF uguale ad 1), a prescindere dalla configurazione attuale del registro EFLAG stesso. Salvataggio e ripristino dei registri: azioni necessarie, essendo il driver asincrono. Driver: non può avere argomenti; non possono essere lasciati da nessuna parte, in quanto le interruzioni possono avvenire in qualunque momento. può operare su variabili globali. Ipotesi di lavoro: coinvolti gate di tipo interrupt; i driver girano con le interruzioni (mascherabili) disabilitate; non si verifica mai annidamento fra driver. G. Frosini Interruzioni Slide 28

G. Frosini Interruzioni Slide 29 Primitive col C++ (1) In C++: non è presente l’istruzione INT; per invocare una primitiva si utilizza un sottoprogramma di interfaccia; tale sottoprogramma può avere argomenti. // file main.cpp, contenente il programma principale extern "C" void primitiva_i(/* argomenti formali */); int main() { … primitiva_i(/* argomenti attuali */); // rit … } # file main.s, contenente il sottoprogramma di interfaccia .text .global primitiva_i primitiva_i: int $TIPO_i // gate di tipo interrupt irit: ret G. Frosini Interruzioni Slide 29

G. Frosini Interruzioni Slide 30 Primitive col C++ (2) # file prim.s, contenente la primitiva vera e propria (a_primitiva) .text .extern c_primitiva_i a_primitiva_i: # routine TIPO_i call c_primitiva_i prit: iret … // file prim.cpp, contenente la parte elaborativa della primitiva (c_primitiva) extern "C" void c_primitiva_i(/* argomenti fittizi + argomenti effettivi*/) { } G. Frosini Interruzioni Slide 30

G. Frosini Interruzioni Slide 31 Primitive col C++ (3) Funzione c_primitiva_i(): costituisce la parte elaborativa della primitiva: una volta salvato EBP e predisposto il nuovo valore di EBP stesso, riferisce gli argomenti a partire da EBP+8; Pila: gli argomenti specificati dalla primitiva_i() non si trovano al posto dovuto (a partire da EBP+8), bensì 4 parole lunghe più in basso, a partire da EBP+8+16 ; Argomenti fittizi: per poter operare correttamente sugli argomenti specificati dalla funzione primitiva_i(), la funzione c_primitiva_i() deve prevedere, prima degli argomenti effettivi, 4 argomenti fittizi, ciascuno costituito da 4 byte (una parola lunga). G. Frosini Interruzioni Slide 31

G. Frosini Interruzioni Slide 32 Driver col C++ # file driv.s .text .extern c_driver_j a_driver_j: pushal # coinvolto un gate di tipo interrupt call c_driver_j movl $0, 0xFEE000B0 # invio della configurazione End Of Interrupt popal iret // file driv.cpp extern "C" void c_driver_i() { … } Ricordare: un driver non può avere argomenti un driver può operare su variabili globali. G. Frosini Interruzioni Slide 32

G. Frosini Interruzioni Slide 33 Sistema di sviluppo (1) Per effettuare programmi di I/O: utilizzo dell’ emulatore QEMU, che emula un Elaboratore 32 PC comprendente: processore x86-32, bus locale con banchi di memoria; controllore di interruzione APIC; bus PCI con bus mastering (Direct Memory Access); bus ATA e 2 unità a disco rigido; bus a 8 bit con tastiera, timer e interfacce seriali; finestra video funzionante in modo testo o in modo grafico. … Emulatore: provvisto di un boot-loader che provvede: a portare il processore da modo (reale) 8086 a modo (protetto) x86-32; a caricare un programma eseguibile da un file UNIX nella memoria dell’elaboratore; a far partire il programma dal suo entry-point (corrispondente all’etichetta _start). G. Frosini Interruzioni Slide 33

G. Frosini Interruzioni Slide 34 Sistema di sviluppo (2) Ipotesi per lo sviluppo di un programma: i file (parte in C++ e parte in Assembler) si trovano tutti e soli in un’unica cartella, dalla quale si emettono i comandi di compilazione-collegamento e di caricamento-esecuzione. Comando di compilazione-collegamento: compile nomefile traduce tutti i file C++ e Assembler contenuti nella cartella corrente, collega i file tradotti ed alcuni facenti parte di un’apposita libreria libce, fra cui il file contenente l’entry point _start; genera il file eseguibile nomefile: se nomefile viene omesso, il file eseguibile è a.out. File eseguibile (entry point _start): richiama i sottoprogrammi ini() e main(). Comando di caricamento-esecuzione: boot nomefile carica il programma eseguibile e fa iniziare il processo di emulazione; produce l’esecuzione del programma a partire dall’entry-point _start; dopo la chiamata del sottoprogramma main() ritorna al sistema operativo UNIX. G. Frosini Interruzioni Slide 34

G. Frosini Interruzioni Slide 35 Libreria libce Tale libreria contiene: un file libce.h, contenente dichiarazioni tipedef e dichiarazioni di funzioni; tanti file con estensione cpp contenenti ciascuno la definizione di una funzione dichiarata in libce.h; altri file con estensione s o cpp, coinvolti (direttamente o indirettamente) dai file precedenti. Fase di collegamento di un programma: con il comando compile (che collega la libreria come ultima), la risoluzione dei nomi viene risolta utilizzando anzitutto i file del programma, quindi i file di libreria. Alcune dichiarazioni typedef presenti in libce.h typedef void* addr; // indirizzo nello spazio di memoria typedef unsigned short ioaddr; // indirizzo nello spazio di I/O typedef unsigned char natb; typedef unsigned short natw; typedef unsigned long natl; Nota: in C++ un indirizzo di memoria può essere dereferenziato (se di tipo void*, richiede una conversione di tipo; un indirizzo di I/O non può essere dereferenziato (lo può essere solo in Assembler). G. Frosini Interruzioni Slide 35

Scrittura di cancelli in IDT (1) Per ogni tipo di interruzione utilizzato: occorre scrivere un gate di tipo interrupt che contenga l’indirizzo della routine che serve la corrispondente interruzione. Sottoprogramma ini(): quello presente nella libreria libce non effettua alcuna elaborazione; se ridefinito dall’utente, deve (tra l’altro) inizializzare i gate utilizzati; per far ciò, utilizza il sottoprogramma componi_gate()): questo compone un gate di tipo interrupt, dato l’indirizzo di una routine. G. Frosini Interruzioni Slide 36

Scrittura di cancelli in IDT (2) # file mod.s, comprendente i contenuti dei file prim.s e driv.s .data .align … # tabella IDT allineata .global idt idt: .fill 256*8, 1 .text .global componi_gate # compone un gate di tipo interrupt, dato l’indirizzo di un gate e di una routine di interruzione componi_gate: … ret .extern c_primitiva_i .global a_primitiva_i # per la funzione ini() (indirizzo da porre in un gate) a_primitiva_i: call c_primitiva_i # routine (primitiva) TIPO_i iret .extern c_driver_j .global a_driver_j # per la funzione ini() (indirizzo da porre in un gate) a_driver_j: pushal # routine (driver) TIPO_j call c_driver_j movl $0, 0xFEE000B0 popal G. Frosini Interruzioni Slide 37

Scrittura di cancelli in IDT (3) //file mod.cpp, comprendente i contenuti dei file prim.cpp e driv.cpp, #include "libce.h" struct gate { natl dw1; natl dw2; }; extern gate idt[]; extern "C" void componi_gate(gate& g, void routine() ); void gate_init(natb num, void routine() ) { gate gg; componi_gate(gg, routine); idt[num] = gg; } extern “C” void a_primitiva_i(); // routine TIPO_i extern “C” void a_driver_j(); // routine TIPO_j void ini() { gate_init(TIPO_i, a_primitiva_i); gate_init(TIPO_j, a_driver_j); … extern "C" void c_primitiva_i(/* argomenti fittizi + argomenti formali effettivi*/) { … } extern "C" void c_driver_j() { … } G. Frosini Interruzioni Slide 38

Predisposizione del controllore APIC (1) Ipotesi: unica fonte di interruzione per piedino. Proprietà indipendenti dalla specifica operazione (predisposte in fase di inizializzazione. segnale costituito da un livello; segnale attivo baso; Proprietà variabili da operazione a operazione: funzione apic_set_MIRQ(), per mascherare/smascherare il piedino su cui arrivano richieste di interruzione; funzione apic_set_VECT(), per associare un tipo al piedino su cui arrivano richieste di interruzione; tali funzioni agiscono sulla tabella interna del controllore; la tabella ha indirizzo base 16; la tabella è costituita da 24 entrate (ciascuna comprende due parole lunghe di 32 bit); la parte bassa di ogni entrata ha indirizzo relativo ir*2, dove ir è il numero d’ordine piedino di richiesta di interruzione (va da 0 a 23). G. Frosini Interruzioni Slide 39

Predisposizione del controllore APIC (2) natl* iIOREGSEL = reinterpret_cast<natl*>(0xFEC00000); natl* iIOWIN = reinterpret_cast<natl*>(0xFEC00010); void apic_set_MIRQ(natb ir, bool v) // ir: numero d’ordine del piedino; v: determina il mascheramento { natl work; // lettura della prima parola lunga dell'entrata ir-esima della tabella interna *iIOREGSEL = 16 + ir*2; work = *iIOWIN; if (v) work |= 0x00010000; // bit n. 16 a 1, mascheramento else work &= 0xFFFEFFFF; // bit n. 16 a 0, smascheramento // scrittura nella prima parola lunga dell'entrata ir-esima della tabella interna *iIOREGSEL = 16 + ir * 2; *iIOWIN = work; } G. Frosini Interruzioni Slide 40

Predisposizione del controllore APIC (3) void apic_set_VECT(natb ir, natb vec) // ir: numero d’ordine del piedino; vec: tipo che vi deve essere associato { natl work; // lettura della prima parola lunga dell'entrata ir-esima della tabella interna *iIOREGSEL) = 16 + ir*2; work = *iIOWIN; // azzeramento (&) e predisposizione (|) dei bit 7-0 con vec work &= 0xFFFFFF00; work |= vec; // scrittura nella prima parola lunga dell’entrata ir-esima della tabella interna *iIOREGSEL = 16 + ir*2; *iIOWIN = work; } Nota: fanno parte del file libce.h le dichiarazioni dei sottoprogrammi: componi_gate(), gate_init(), apic_set_MIRQ(), apic_set_VECTOR() fanno parte della libreria i file contenenti le definizione di tali sottoprogrammi e delle variabili IDT, iIOREGSEL, iIOWIN. G. Frosini Interruzioni Slide 41

Interfaccia gestita a interruzione (1) Interfaccia in grado di funzionare a interruzione di programma, sia per operazioni di ingresso che di uscita: RBR A1-A0 D7-D0 EXIO 1 TBR 2 CTRI 3 CTRO /RD /WR /S INTI CLK INTO G. Frosini Interruzioni Slide 42

Interfaccia gestita a interruzione (2) L’interfaccia invia una richiesta di interruzione quando: il buffer di ingresso diviene pieno (RBR contiene un nuovo byte prelevato dal dispositivo); la richiesta viene inviata tramite il piedino INTI; il buffer di uscita diviene vuoto (il byte in TBR è stato inviato al dispositivo ); la richiesta viene inviata tramite il piedino INTO. Accesso a RBR (lettura) o a TBR (scrittura) effettuato dal driver: costituisce anche una risposta alla richiesta di interruzione; l’interfaccia può rimuovere la richiesta stessa e iniziare un nuovo trasferimento. L’interfaccia può essere abilitata (apposito bit a 1) o disabilitata (apposito bit 0) a inviare richieste di interruzione: bit apposito: bit meno significativo dei registri CTRI e CTRO (ConTrol Register In/Out), rispettivamente; una volta effettuata l’abilitazione, l’interfaccia genera immediatamente una richiesta di interruzione se il buffer di ingresso è già pieno o il buffer di uscita è già vuoto. G. Frosini Interruzioni Slide 43

Operazioni di I/O a interruzione (1) Interfaccia: ogni volta che è pronta a trasferire un dato, invia una richiesta di interruzione; quando la richiesta viene accettata dal processore, va in esecuzione un driver di interruzione che provvede a trasferire il dato. Durante l’intervallo di tempo fra una richiesta di interruzione e un’altra: possono essere compiute utilmente altre elaborazioni. Trasferimento di un singolo dato: richiede più tempo nel caso di interruzione che non nel caso di controllo di programma; il meccanismo di interruzione, infatti, prevede accessi aggiuntivi in memoria. Meccanismo di interruzione: risulta globalmente vantaggioso in quanto elimina le cosiddette attese attive. Driver: ogni volta che va in esecuzione, verifica se trattasi dell’ultimo dato da trasferire; in caso affermativo, disabilita l’interfaccia a generare richieste di interruzione; in ogni caso trasferisce un dato e invia al controllore la configurazione End Of Interrupt; Trasferimento di N dati: generazione di N richieste di interruzione ed esecuzione del driver per N volte. G. Frosini Interruzioni Slide 44

Operazioni di I/O a interruzione (2) spesso sono organizzate come primitive; è bene che il programma non acceda direttamente alle interfacce. Realizzazione delle operazioni di I/O: risulta più naturale se si suppone che le operazioni stesse siano sincrone: il programma che le effettua si blocca in attesa della loro terminazione; esso viene sbloccato solo quando l’operazione è terminata. Evitare attese attive: bisogna supporre chi si operi in un ambiente multiprogrammato; quando un programma è bloccato in attesa che sia terminata una operazione di I/O, viene eseguito un altro programma. G. Frosini Interruzioni Slide 45

Meccanismo di sincronizzazione (1) Meccanismo semplice (non realistico): semaforo di sincronizzazione: costituito da una variabile binaria; due sottoprogrammi che hanno per argomento il numero d’ordine di un semaforo: sem_wait(): inizializza la variabile a 0; ciclicamente, finché la variabile non vale 1, tiene in attesa il programma. sem_signal(): pone la variabile a 1; Variabile di sincronizzazione: viene posta a 1 dal driver di interruzione; nel sottoprogramma sem_wait(), il ciclo deve avere le interruzioni abilitate. Argomento attuale dei due sottoprogrammi: stesso numero d’ordine di semaforo. Meccanismo utilizzato: anche se non realistico, consente di fare programmi di prova. G. Frosini Interruzioni Slide 46

Meccanismo di sincronizzazione (2) .data sem: .fill N, 1 # N semafori .text # sottoprogramma sem_wait(natl num_sem); .global sem_wait sem_wait: pushl %eax # nella realtà: esecuzione di altro programma movl 8(%esp), %eax # numero d’ordine del semaforo (num_sem) movb $0, sem(%eax) sti aspetta: testb $1, sem(%eax) jz aspetta popl %eax ret # sottoprogramma sem_signal(natl num_sem); .global sem_signal sem_signal: pushl %eax # nella realtà: riabilitazione del programma bloccato movl 8(%esp), %eax # numero d’ordine del semaforo (num_sem) movb $1, sem(%eax) popl %eax G. Frosini Interruzioni Slide 47

Meccanismo di sincronizzazione (3) Nota: fanno parte del file libce.h le dichiarazioni dei sottoprogrammi sem_wait() e sem_signal(); fanno parte della libreria i file contenenti le definizione dell’array sem e dei sottoprogrammi sem_wait() e sem_signal(). G. Frosini Interruzioni Slide 48

G. Frosini Interruzioni Slide 49 File mod.s # file mod.s, contenente la primitiva di I/O e il corrispondente driver di I/O … .text .extern c_primIO_i .global a_primIO_i # per la funzione ini() (indirizzo da porre in un gate) a_primIO_i: # routine (primitiva) TIPO_i call c_primIO_i iret .extern c_drivIO_j .global a_drivIO_j # per la funzione ini() (indirizzo da porre in un gate) a_drivIO_j: # routine (driver) TIPO_j pushal call c_drivIO_j movl $0, 0xFEE000B0 popal G. Frosini Interruzioni Slide 49

G. Frosini Interruzioni Slide 50 File mod.cpp // file mod.cpp, contenente ini(), c_primIO_i() e c_drivIO_j() #include "libce.h" const natl IR_t = …; // numero d’ordine del piedino dello IO APIC const natl sincr_s = …; // numero d’ordine del semaforo utilizzato void ini_ip_interf() { … // inizializzazione dell’interfaccia } extern “C” void a_primIO_i(); // routine TIPO_i extern “C” void a_drivIO_j(); // routine TIPO_j void ini() { ini_ip_interf(); gate_init(TIPO_i, a_primIO_i); gate_init(TIPO_j, a_drivIO_j); apic_set_VECT(IR_t, TIPO_j); apic_set_MIRQ(IR_t, false); // abilitazione del piedino IR_t dello APIC … extern "" void c_primIO_i(/* argomenti fittizi + argomenti formali effettivi*/) { … sem_wait(sincr_s); … } extern "C" void c_drivIO_j() { ... sem_signal(sincr_s); … } G. Frosini Interruzioni Slide 50

Funzioni di libreria per l’I/O Funzioni dichiarate nel file libce.h e definite nella libreria (scritte in Assembler) per leggere da, o scrivere in, un registro dello spazio di I/O: extern "C" void inputb(ioaddr ireg, natb &a); trasferisce dal registro di indirizzo ireg nella variabile a extern "C" void outputb(natb a, ioaddr ireg); trasferisce dalla variabile a al registro di indirizzo ireg extern "C" void inputw(ioaddr ireg, natw &a); extern "C" void outputw(natw a, ioaddr ireg); extern "C" void inputl(ioaddr ireg, natl &a); extern "C" void outputl(natl a, ioaddr ireg); G. Frosini Interruzioni Slide 51

G. Frosini Interruzioni Slide 52 Ingresso dati Programma che intende fare un’operazione di ingresso dati: invoca una primitiva di I/O, sia read_n(); argomenti di read_n(): numero di byte da trasferire; indirizzo del buffer di memoria nel quale devono essere immessi i byte. La primitiva read_n() deve: trasferire il valore degli argomenti in due variabile cont_in e punt_in accessibili anche al driver; abilitare l’interfaccia a generare richieste di interruzione in ingresso; richiamare il sottoprogramma sem_wait(). Il driver di interruzione driver_in(), ogni volta che va in esecuzione deve: decrementare cont_in; se cont_in è uguale a 0: disabilitare l’interfaccia a generare richieste di interruzione in ingresso; richiamare il sottoprogramma sem_signal(); in ogni caso: trasferire un byte da interfaccia a memoria; incrementare punt_in ; inviare la configurazione End_Of_Interrupt. G. Frosini Interruzioni Slide 52

G. Frosini Interruzioni Slide 53 Primitiva read_n() // file leggi.cpp #include <libce.h> natb buffr[N]; extern "C" void read_n(natl nn, natb vv[]); int main() { natl quanti; // … quanti = 10; // massimo N read_n(quanti, buffr); // ... return 0; } # file leggi.s .text .global read_n read_n: int $150 ret G. Frosini Interruzioni Slide 53

Routine assembler a_read_n e a_driverin_n # file mod_leggi.s .text .extern c_read_n .global a_read_n # per la funzione ini() a_read_n: # routine INT $150 call c_read_n iret .extern c_driverin_n .global a_driverin_n # per la funzione ini() a_driverin_n: # routine associata al tipo 50 pushal call c_driverin_n movl $0, 0xFEE000B0 popal G. Frosini Interruzioni Slide 54

G. Frosini Interruzioni Slide 55 Inizializzazioni // file mod_leggi.cpp // Interfaccia collegata per l’ingresso dati al piedino 4 dello IO APIC #include <libce.h> const natl sincr_s = 1; // si usa il semaforo numero 1 const ioaddr iRBR = 0x63E0; const ioaddr iTBR = 0x63E1; const ioaddr iCTRI = 0x63E2; const ioaddr iCTRO = 0x63E3; natl cont_in; natb* punt_in; void ini_ip_interf_in() { outputb(0x00, iCTRI); // disabilit. richieste di interruzione ingresso } extern "C" void a_read_n(); extern "C" void a_driverin_n(); void ini() { ini_ip_interf_in(); gate_init(150, a_read_n); gate_init(50, a_driverin_n); apic_set_VECT(4, 50); // associazione del tipo 50 al piedino 4 apic_set_MIRQ(4, false); // abilit. piedino n. 4 dello IO APIC G. Frosini Interruzioni Slide 55

Funzioni C++ c_read_n() e c_driver_n() extern "C" void c_read_n(natl a, natl b, natl c, natl d, natl nn, natb vv[]) { cont_in = nn; punt_in = vv; outputb(0x01, iCTRI); // abilit. richieste di interruzione ingresso sem_wait(sincr_s); } extern "C" void c_driverin_n() { natb c; cont_in--; if (cont_in == 0) { outputb(0x00, iCTRI); // disab. richieste di interruzione ingresso sem_signal(sincr_s); inputb(iRBR, c); *punt_in = c; // trasferimento in memoria punt_in++; G. Frosini Interruzioni Slide 56

Osservazioni sul driver prima di trasferire l’ultimo dato, oltre a disabilitare l’interfaccia, richiamano anche il sottoprogramma sem_signal(): non è concettualmente corretto richiamare sem_signal() prima che i dati siano stati tutti trasferiti; tuttavia non si verificano malfunzionamenti perché le interruzioni mascherabili sono disabilitate. Esecuzione di un driver: inizia quando arriva un’interruzione durante il ciclo di attesa del sottoprogramma sem_wait(); termina (ritornando al ciclo di attesa stesso) solo quando è giunto a termine: ha effettuato tutte le operazioni specificate (nell’ultima esecuzione, quando ha messo a 1 il semaforo e ha effettuato il trasferimento dell’ultimo dato). Driver con le interruzioni mascherabili disabilitate: non vi è il rischio che, prima che il driver finisca, vada in esecuzione una qualsivoglia routine di interruzione che magari esamini il valore del semaforo, trovandolo già ad 1 quando i trasferimenti dei dati non sono stati tutti effettuati. G. Frosini Interruzioni Slide 57

Terminazione determinata da un particolare byte Condizione di terminazione di una operazione: può anche essere determinata, oltre che dal conteggio dei byte, anche dalla lettura dall’interfaccia di un particolare byte, o dalla scrittura nell’interfaccia di un particolare byte. Operazione di lettura: in questo caso il driver va così modificato: disabilita l’interfaccia a generare richieste di interruzione; legge un dato; se il dato letto non è quello di terminazione, riabilita l’interfaccia a generare richieste di interruzione. Operazione di scrittura: in questo caso il driver subisce modeste modifiche: esamina ogni dato prelevato dal buffer; se il dato è di terminazione, disabilita l’interfaccia a generare richieste di interruzione come se il conteggio fosse arrivato a 0. G. Frosini Interruzioni Slide 58

G. Frosini Interruzioni Slide 59 Buffer di memoria Buffer di memoria utilizzati nelle primitive read_n() e write_n(): sono stati definiti come variabili globali; se fossero definiti locali ai programmi principali di lettura o di scrittura, verrebbero ad essere memorizzati nelle loro pile. Quando da un’interfaccia arriva una richiesta di interruzione: manda in esecuzione un driver; il programma che sta effettuando un’operazione di I/O è bloccato sul sottoprogramma wait(); nella realtà la sua pila non è accessibile, ma è accessibile quella di un eventuale altro programma che nel frattempo può essere eseguito. Queste ultime considerazioni saranno comprese a pieno quando verrà trattata la multiprogrammazione. G. Frosini Interruzioni Slide 59