6. HAL and IDT ENGI 3655 Lab Sessions. Richard Khoury2 Textbook Readings  Interrupts ◦ Section 13.2.2  Hardware Abstraction Layer ◦ Section 22.3.1.

Slides:



Advertisements
Similar presentations
Chapter 2 (cont.) An Introduction to the 80x86 Microprocessor Family Objectives: The different addressing modes and instruction types available The usefulness.
Advertisements

1/1/ / faculty of Electrical Engineering eindhoven university of technology Architectures of Digital Information Systems Part 1: Interrupts and DMA dr.ir.
Unit 4 Chapter-1 Multitasking. The Task State Segment.
Intel MP.
1/1/ / faculty of Electrical Engineering eindhoven university of technology Introduction Part 3: Input/output and co-processors dr.ir. A.C. Verschueren.
Microprocessors system architectures – IA32 real and virtual-8086 mode Jakub Yaghob.
Lecture 6 Machine Code: How the CPU is programmed.
Operating Systems: Segments 1 Segmentation Hardware Support single user program system: – wish somehow to relocate address 0 to after operating system.
Interrupts What is an interrupt? What does an interrupt do to the “flow of control” Interrupts used to overlap computation & I/O – Examples would be console.
Page-Faults in Linux How can we study the handling of page-fault exceptions?
Exceptions and Interrupts How does Linux handle service- requests from the cpu and from the peripheral devices?
X86 segmentation, page tables, and interrupts 3/17/08 Frans Kaashoek MIT
PC hardware and x86 3/3/08 Frans Kaashoek MIT
1 ICS 51 Introductory Computer Organization Fall 2006 updated: Oct. 2, 2006.
1 Lecture 5: Procedures Assembly Language for Intel-Based Computers, 4th edition Kip R. Irvine.
Linux Operating System
Hardware Support for Operating Systems Sunny Gleason Vivek Uppal COM S 414
Introduction to Interrupts
Homework / Exam Return and Review Exam #1 Reading Machine Projects
ICS312 Set 3 Pentium Registers. Intel 8086 Family of Microprocessors All of the Intel chips from the 8086 to the latest pentium, have similar architectures.
Interrupts – (Chapter 12)
UNIT 2 Memory Management Unit and Segment Description and Paging
System Calls 1.
Interrupts  Interrupt is a process where an external device can get the attention of the microprocessor.  The process starts from the I/O device  The.
Micro-Computer Applications: Procedures & Interrupts Dr. Eng. Amr T. Abdel-Hamid ELECT 707 Fall 2011.
CEG 320/520: Computer Organization and Assembly Language ProgrammingIntel Assembly 1 Intel IA-32 vs Motorola
Interrupts. What Are Interrupts? Interrupts alter a program’s flow of control  Behavior is similar to a procedure call »Some significant differences.
6.828: PC hardware and x86 Frans Kaashoek
Windows Kernel Internals Traps, Interrupts, Exceptions
The Pentium Processor.
Multitasking Mr. Mahendra B. Salunke Asst. Prof. Dept. of Computer Engg., STES SITS, Narhe, Pune-41 STES Sinhgad Institute of Tech. & Science Dept. of.
CSNB374: Microprocessor Systems Chapter 5: Procedures and Interrupts.
1 ICS 51 Introductory Computer Organization Fall 2009.
Virtual 8086 Mode  The supports execution of one or more 8086, 8088, 80186, or programs in an protected-mode environment.  An 8086.
Microprocessor system architectures – IA32 tasks Jakub Yaghob.
Chapter 2 Parts of a Computer System. 2.1 PC Hardware: Memory.
Functions/Methods in Assembly
7. IRQ and PIC ENGI 3655 Lab Sessions. Richard Khoury2 Textbook Readings  Interrupts ◦ Section
4. Kernel and VGA ENGI 3655 Lab Sessions. Richard Khoury2 Textbook Readings  None.
Interrupt driven I/O Computer Organization and Assembly Language: Module 12.
Assembly 08 Interrupts. Introduction Interrupts are similar to procedures –They are used to alter a program’s control flow –The interrupt service is also.
10. Epilogue ENGI 3655 Lab Sessions.  We took control of the computer as early as possible, right after the end of the BIOS  Our multi-stage bootloader.
Information Security - 2. Task Switching Every process has an associated Task State Segment, whose starting point is stored in the Task register. A task.
BIOS and DOS Interrupts Basic Input /Outpu System Disk Operating System.
Interrupts and Exception Handling. Execution We are quite aware of the Fetch, Execute process of the control unit of the CPU –Fetch and instruction as.
Microprocessors CSE- 341 Dr. Jia Uddin Assistant Professor, CSE, BRAC University Dr. Jia Uddin, CSE, BRAC University.
Lecture 7 Interrupt ,Trap and System Call
Microprocessor Architecture
Homework / Exam Return and Review Exam #1 Reading Machine Projects
Homework Reading Machine Projects Labs
Architectures of Digital Information Systems Part 1: Interrupts and DMA dr.ir. A.C. Verschueren Eindhoven University of Technology Section of Digital.
An Interrupt is either a Hardware generated CALL (externally derived from a hardware signal) OR A Software-generated CALL (internally derived from.
Interrupts and exceptions
Assembly language.
Interrupts and signals
MICROPROCESSOR BASED SYSTEM DESIGN
Microprocessor and Assembly Language
Operating Systems Engineering
Microprocessor Systems Design I
Anton Burtsev February, 2017
Anton Burtsev February, 2017
Homework Reading Labs S&S Extracts ,
Interrupts – (Chapter 12)
Basic Microprocessor Architecture
x86 segmentation, page tables, and interrupts
CS 301 Fall 2002 Computer Organization
The Microprocessor & Its Architecture
CNET 315 Microprocessor & Assembly Language
Low-Level Thread Dispatching on the x86
CHAPTER 6 INPUT/OUTPUT PROGRAMMING
Presentation transcript:

6. HAL and IDT ENGI 3655 Lab Sessions

Richard Khoury2 Textbook Readings  Interrupts ◦ Section  Hardware Abstraction Layer ◦ Section

Richard Khoury3 Hardware Abstraction Layer  Last week we created an interface to avoid using “int” and “char” because they might be too platform-dependant ◦ We want our OS to work on any hardware  But our OS does need to work with the hardware ◦ We can’t hide technical details and specificities forever

Richard Khoury4 Hardware Abstraction Layer  We’ll write declarations for the functions we need that are not system-specific ◦ Using our interface data types ◦ Put them all in header files  We’ll write system-specific function implementations ◦ One version for each system we want to support ◦ They all implement the same header file  We’ll pick the one we need ◦ Dynamically at run time, by loading the right module ◦ At linking time, picking the right object file  That is a hardware abstraction layer (HAL) ◦ Our data type definitions are part of it

Richard Khoury5 Hardware Abstraction Layer  Our initial HAL will have few parts  HAL ◦ CPU  Registers  GDT  IDT ◦ Basic memory-handling functions

Richard Khoury6 Hardware Abstraction Layer  HAL.h ◦ Included in our main file ◦ Defines the HAL initialization and shutdown functions extern uint32_t hal_initialize(); extern uint32_t hal_shutdown(); ◦ The initialize function is the only one the kernel calls; it will initialize everything else

Richard Khoury7 HAL CPU  The initialize and shutdown functions activate and deactivate the hardware ◦ For now, our only hardware is the CPU  CPU.h extern uint32_t cpu_initialize (); extern void cpu_shutdown ();  Registers.h struct _R16BIT { uint16_t ax, bx, cx, dx, si, di, bp, sp, es, cs, ss, ds, flags; uint8_t cflag; };

Richard Khoury8 HAL GDT  The CPU initialization will create a new GDT ◦ To put the GDT under the control of our OS rather than the bootloader ◦ For now, just the same GDT as before, but written with C structures  Recall: the GDT descriptors are 8-byte structures, and we had five of them loaded into the processor ◦ Also, specific to Intel processor; not part of the interface, so included in i86.c, an implementation of CPU.h

Richard Khoury9 HAL GDT  We’ll create a GDT structure to store the information struct gdt_descriptor { uint16_tlimit; uint16_tbaseLo; uint8_tbaseMid; uint8_taccess; uint8_tgran; uint8_tbaseHi; } __attribute__((packed));  We can create each of our five descriptors with these  But then we need a place to store them static struct gdt_descriptor _gdt [MAX_DESCRIPTORS];

Richard Khoury10 HAL GDT  Next we can define the descriptors  We can even define constants to make the code more readable /*Bits 5-6: Privilege*/ #define I86_GDT_DESC_RING00x0000 //_00_____ #define I86_GDT_DESC_RING10x0020 //_01_____ #define I86_GDT_DESC_RING20x0040 //_10_____ #define I86_GDT_DESC_RING30x0060 //_11_____  And we create each descriptor gdt_set_descriptor(uint32_t i, uint64_t base, uint64_t limit, uint8_t access, uint8_t gran) ; code descriptor dw 0FFFFh ; limit low dw 0 ; base low db 0 ; base middle db b ; access db b ; granularity db 0 ; base high

Richard Khoury11 HAL GDT  Recall that loading the GDT into the CPU requires two things  A special structure representing the start and size of the GDT toc: dw end_of_gdt - gdt_data - 1 dd gdt_data  A special Assembly instruction lgdt [toc]  We’ll need to do that from C

Richard Khoury12 HAL GDT  We’ll start by defining the GDT structure struct gdtr { uint16_tm_limit; uint32_tm_base; } __attribute__((packed)); static struct gdtr _gdtr; _gdtr.m_limit = (sizeof (struct gdt_descriptor) * MAX_DESCRIPTORS)-1; _gdtr.m_base = (uint32_t)&_gdt[0];  We’ll need an external Assembly function to load the GDT extern void gdt_install ();

Richard Khoury13 HAL GDT  Next, we create a new Assembly include file ◦ “GlobalCFunctions.inc” ◦ Include it in our Kernel  Needs to work with our C function ◦ Define the function to load the GDT global _gdt_install ◦ Use the GDT data structure extern __gdtr ◦ Note the extra _ character

Richard Khoury14 HAL GDT  Then write the function in Assembly _gdt_install: ◦ Load the GDT into its special register using the special instruction lgdt [__gdtr] ◦ Put the offset of the data segment in the registers mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ◦ Far-jump to the offset of the code segment jmp 0x08:endgdt endgdt: ret

Richard Khoury15 Hardware Abstraction Layer HAL.h i86.cHAL.c CPU.h main.c Intel 80x86 processor with VGA-compatible video card AMD-specific implementation files System-specific implementation files Hardware- independent interface Kernel ENGI3655 computers GDT.h/c IDT.h/c Mode7.c Mode7.h Data types (stdint.h) Registers.h

Richard Khoury16 Interrupts  OS needs to interact with the I/O hardware ◦ We already did some of that, making the bootloader interact with the screen (int 10h) and the disk (int 13h) ◦ For optimal performance, OS should be informed immediately when an I/O device needs attention ◦ When ready, run special I/O code  OS needs to be immediately informed of exceptions in programs ◦ Illegal code: needs to substitute special exception- handling code

Richard Khoury17 Interrupts  Different functions, but both require the same kind of action ◦ Interrupt current process’s execution ◦ Jump to special code and execute ◦ Return if possible  Interrupts ◦ Hardware Interrupts ◦ Software Interrupts (traps)

Richard Khoury18 Hardware Interrupts I/O Controller Input or output ready, or error Translate IRQ into Interrupt no. Send IRQ Signal CPU’s Interrupt Request line Execute instruction Check IR line Execute instruction Check IR line Jump to location pointed in IDT Save state information Interrupt Handler Routine Restore state information Perform regular I/O functions Programmable Interrupt Controller (PIC) CPU OS Execute IHR

Richard Khoury19 Software Interrupts (Traps) Execute instruction Exception! Generate Interrupt number Jump to location pointed in IDT Save pointer to instruction Interrupt Handler Routine Return if possible CPU OS Execute IHR

Richard Khoury20 Handling Interrupts  Our OS doesn’t handle interrupts yet  Try it: add an interrupt in the C kernel using inline Assembly code asm volatile ("int $0x3");  What happens?

Richard Khoury21 For This Lab...  We will handle interrupts ◦ Build an interrupt descriptor table (IDT) ◦ Write interrupt handlers

Richard Khoury22 Interrupt Vector Table  A table of 256 entries ◦ Each one represents a kind of event that requires interrupting the CPU ◦ Each one is 4 bytes large: it consists of a memory address (2 bytes offset + 2 bytes segment)  When an interrupt vector (0x10 for example) is generated, the CPU looks up the entry (0x10 * 4 in the IVT) and jumps to that address in memory ◦ That address should contain executable code to handle whatever generated that interrupt

Richard Khoury23 Interrupt Vector Table  But wait!  Recall: before switching to protected mode, our second-state bootloader disabled interrupts  And we never enabled them again afterwards  IVT is only accessible from Real Mode  If we want to use interrupts from Protected Mode, we’ll need to set up an Interrupt Descriptor Table

Richard Khoury24 Interrupt Descriptor Table  Like the IVT, the IDT has 256 entries  Each one is 8 bytes long  Three different descriptor types ◦ Interrupt Gates: For I/O interrupts ◦ Trap Gates: For exception interrupts  They are almost identical, except that interrupts are disabled by interrupt gate and not by trap gate, so IG is better for hardware interrupts ◦ Task Gates: For task-switching interrupts

Richard Khoury25 Descriptor Structure BitsInterrupt GateTrap GateTask Gate 0-15Interrupt Handler Routine address (0-15) Not used 16-31Code Segment SelectorTask State Segment (TSS) Selector 32-35Not Used 36-39Reserved (set to zero)Not used

Richard Khoury26 Descriptor Structure BitsInterrupt GateTrap GateTask Gate Type 01110: 32 bits 00110: 16 bits 01111: 32 bits 00111: 16 bits Privilege Ring Level (00 highest – 11 lowest) 470/1 = Segment is absent/present 48-63Interrupt Handler Routine address (16-31) Not used

Richard Khoury27 Descriptor Structure  Easy to represent as a C structure ◦ Remember our C data type interface from last week? struct idt_descriptor { uint16_tbaseLo; uint16_tsel; uint8_treserved; uint8_tflags; uint16_tbaseHi; };

Richard Khoury28 Interrupt Descriptor Table  256 Interrupts defined by Intel for the 80x86  0: Divide by 0  1: Debugger single step  2: Non-maskable interrupt  3: Debugger breakpoint  4: Overflow  5: Out of bounds  6: Undefined Operation Code (OPCode) instruction  7: No coprocessor  8: Double fault  9: Coprocessor segment overrun  10: Invalid Task State Segment (TSS)  11: Segment not present  12: Stack fault  13: General protection fault  14: Page fault  15 is unassigned  16: Coprocessor error  17: Alignment check (486+ Only)  18: Machine check (Pentium/586+ Only)  are reserved by Intel  are free for software use

Richard Khoury29 Interrupt Descriptor Table  The IDT is a table of 256 interrupt descriptors ◦ We’ve already seen the idt_descriptor data structure ◦ An array of them is simply: static struct idt_descriptor_idt[i86_MAX_INTERRUPTS];  We’ll create two interface functions to the IDT ◦ i86_install_ir : to modify an interrupt descriptor in our table ◦ i86_idt_initialize : to initialize the table with the default 256 descriptors  Each descriptor includes the address of the interrupt handler routine

Richard Khoury30 Interrupt Handler Routine  Sometimes called Interrupt Service Routine (ISR)  The function that dictates what to do when a given interrupt occurs  There are 256 interrupts ◦ are free for software use – we won’t write complex functions for them ◦ We’ll need functions for int 0 to 31 ◦ For now, we’ll simply make a default handler function that displays an error message and runs an endless loop i86_default_handler()

Richard Khoury31 Installing a Handler  Handler routine address is bits 0-15 and of interrupt descriptor structure for (i=0; i<I86_MAX_INTERRUPTS; i++) i86_install_ir ((I86_IRQ_HANDLER)i86_default_handler); i86_install_ir (I86_IRQ_HANDLER irq) { uint64_t uiBase =(uint64_t)&(*irq); _idt[i].baseLo =(uiBase & 0xffff); _idt[i].baseHi =((uiBase >> 16) & 0xffff);}

Richard Khoury32 Installing a Handler  The i86_install_ir function also needs you to specify the interrupt number the function is for, the code segment (0x8) and the descriptor attributes ◦ Bits 40-44: Descriptor type ◦ Bits 45-46: Privilege ring ◦ Bits 47: Descriptor present/abscent ◦ Values defined as constants in idt.h #define I86_IDT_DESC_RING00x00//_00_____ #define I86_IDT_DESC_RING30x60//_11_____

Richard Khoury33 Loading the IDT  Like the GDT, the IDT is simply installed by loading the base address and size into a special CPU register  We’ll create a C structure struct idtr { uint16_tlimit; uint32_tbase; } __attribute__((packed)); struct idtr _idtr;  Set them to the right values _idtr.limit= sizeof(struct idt_descriptor)*I86_MAX_INTERRUPTS-1; _idtr.base= (uint32_t)&_idt[0];  And define an extern Assembly function extern void idt_install();

Richard Khoury34 Loading the IDT  The Assembly function is even simpler than the one to load the GDT global _idt_install extern __idtr _idt_install: lidt [__idtr] ret

Richard Khoury35 Loading the IDT  Once it’s done, test it  We already added an interrupt in the C kernel asm volatile ("int $0x3");  What happens now?

Richard Khoury36 Interrupt Handler Routine  Now we only have one common handler routine that does nothing  We’ll build better routines for our first 32 interrupts ◦ Save the stack ◦ Display a personalized message ◦ Reload the stack  Clearly, we’ll need a good mix of Assembly and C functions

Richard Khoury37 Interrupt Handler Routine  The routine called by an interrupt will be divided in three parts  Low Part ◦ Push error code on stack (if not done automatically) ◦ Push interrupt number on stack ◦ Jump to common part  Common Part ◦ Push all registers on stack ◦ Call top part  Top Part ◦ Take action specific to interrupt  Low and Common are in Assembly, top in C

 Six interrupts automatically push an error code before the Low Part Interrupt Handler Routine Richard Khoury38  0: Divide by 0  1: Debugger single step  2: Non-maskable interrupt  3: Debugger breakpoint  4: Overflow  5: Out of bounds  6: Undefined Operation Code (OPCode) instruction  7: No coprocessor  8: Double fault  9: Coprocessor segment overrun  10: Invalid Task State Segment (TSS)  11: Segment not present  12: Stack fault  13: General protection fault  14: Page fault  15 is unassigned  16: Coprocessor error  17: Alignment check (486+ Only)  18: Machine check (Pentium/586+ Only)  are reserved by Intel  are free for software use

Richard Khoury39 Interrupt Handler Routine (low part)  Structure of Low Part (for interrupt #) global _isr# _isr#: cli push byte 0 (if not done automatically) push byte # jmp isr_common_stub  The 0 byte is a dummy error code ◦ Not needed for traps

Richard Khoury40 Interrupt Handler Routine (common)  Structure of Common Part (for all int) isr_common_stub: ◦ Push all registers pusha push (ds, es, fs, gs) ◦ Load the kernel data segment descriptor mov ax, 0x10 mov (ds, es, fs, gs), ax ◦ Call the function mov eax, esp push eax mov eax, _fault_handler call eax ◦ Pop all registers reverse order and far-return pop … add esp, 8 iret

Richard Khoury41 Interrupt Handler Routine (top part)  Top Part is a C function void fault_handler() { ◦ Do something specific to each interrupt }  Declared as “extern” in the Assembly code  Problem: how does the function know which interrupt number has been called?

Richard Khoury42 Interrupt Handler Routine  Answer: It has been pushed on the stack by the Low Part  We can access it in C with a register data structure (Registers.h) struct isrregs { uint32_t gs, fs, es, ds; uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; uint32_t int_no, err_code; uint32_t eip, cs, eflags, useresp, ss; }; eax gs, fs, es, ds pusha (edi, esi, ebp, esp, ebx, edx, ecx, eax) Interrupt number Error code eip, cs, eflags, useresp, ss Top of stack These were pushed automatically by the CPU before our Low Part

Richard Khoury43 Interrupt Handler Routine (top part)  Now we can pass it to our Top Part and use it void fault_handler(struct isrregs *r) { ◦ Do something specific to each r->int_no }  But what to do? ◦ We need a generic default behaviour (displaying a message) ◦ We want personalized default messages for the first 32 interrupts ◦ We want to be able to easily “plug in” new custom interrupt handlers for the first 32 interrupts

 How to plug in new ISR? ◦ An ISR is a function – it has an address ◦ So we’ll keep track of ISR addresses void *idt_routines[32]; ◦ Then we can plug in an ISR by putting in the function’s address at the entry in the arrat void i86_install_handler(uint32_t idt, void (*handler)(struct isrregs *r)) { idt_routines[idt] = handler; } ◦ We can also unplug an ISR by setting that entry in the array to 0 void i86_uninstall_handler(uint32_t idt) {idt_routines[idt] = 0;} Interrupt Handler Routine (plug in) Richard Khoury44

 Our top part can check if there is a custom function installed for an interrupt by checking the array void (*handler)(struct isrregs *r); handler = idt_routines[r->int_no]; if ( (uint32_t)handler != 0 ) { handler(r);} else { default behaviour }  So don’t forget to initialize all entries to 0! Interrupt Handler Routine (plug in) Richard Khoury45

Richard Khoury46 Lab Assignment  Add the HAL to your kernel  Write the three-part Interrupt Handler Routines for the first 32 interrupts ◦ Don’t forget to install your new handlers in the IDT instead of the default handler!  Test with inline Assembly interrupts and make sure it displays the right message! ◦ When you compile the IDT you will get a “cast from pointer to integer” warning – that’s normal