add lab answers
This commit is contained in:
197
labcodes_answer/lab2_result/kern/trap/trap.c
Normal file
197
labcodes_answer/lab2_result/kern/trap/trap.c
Normal file
@@ -0,0 +1,197 @@
|
||||
#include <defs.h>
|
||||
#include <mmu.h>
|
||||
#include <memlayout.h>
|
||||
#include <clock.h>
|
||||
#include <trap.h>
|
||||
#include <x86.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <console.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
#define TICK_NUM 100
|
||||
|
||||
static void print_ticks() {
|
||||
cprintf("%d ticks\n",TICK_NUM);
|
||||
#ifdef DEBUG_GRADE
|
||||
cprintf("End of Test.\n");
|
||||
panic("EOT: kernel seems ok.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* *
|
||||
* Interrupt descriptor table:
|
||||
*
|
||||
* Must be built at run time because shifted function addresses can't
|
||||
* be represented in relocation records.
|
||||
* */
|
||||
static struct gatedesc idt[256] = {{0}};
|
||||
|
||||
static struct pseudodesc idt_pd = {
|
||||
sizeof(idt) - 1, (uintptr_t)idt
|
||||
};
|
||||
|
||||
/* idt_init - initialize IDT to each of the entry points in kern/trap/vectors.S */
|
||||
void
|
||||
idt_init(void) {
|
||||
/* LAB1 YOUR CODE : STEP 2 */
|
||||
/* (1) Where are the entry addrs of each Interrupt Service Routine (ISR)?
|
||||
* All ISR's entry addrs are stored in __vectors. where is uintptr_t __vectors[] ?
|
||||
* __vectors[] is in kern/trap/vector.S which is produced by tools/vector.c
|
||||
* (try "make" command in lab1, then you will find vector.S in kern/trap DIR)
|
||||
* You can use "extern uintptr_t __vectors[];" to define this extern variable which will be used later.
|
||||
* (2) Now you should setup the entries of ISR in Interrupt Description Table (IDT).
|
||||
* Can you see idt[256] in this file? Yes, it's IDT! you can use SETGATE macro to setup each item of IDT
|
||||
* (3) After setup the contents of IDT, you will let CPU know where is the IDT by using 'lidt' instruction.
|
||||
* You don't know the meaning of this instruction? just google it! and check the libs/x86.h to know more.
|
||||
* Notice: the argument of lidt is idt_pd. try to find it!
|
||||
*/
|
||||
extern uintptr_t __vectors[];
|
||||
int i;
|
||||
for (i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i ++) {
|
||||
SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
|
||||
}
|
||||
lidt(&idt_pd);
|
||||
}
|
||||
|
||||
static const char *
|
||||
trapname(int trapno) {
|
||||
static const char * const excnames[] = {
|
||||
"Divide error",
|
||||
"Debug",
|
||||
"Non-Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Overflow",
|
||||
"BOUND Range Exceeded",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Invalid TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection",
|
||||
"Page Fault",
|
||||
"(unknown trap)",
|
||||
"x87 FPU Floating-Point Error",
|
||||
"Alignment Check",
|
||||
"Machine-Check",
|
||||
"SIMD Floating-Point Exception"
|
||||
};
|
||||
|
||||
if (trapno < sizeof(excnames)/sizeof(const char * const)) {
|
||||
return excnames[trapno];
|
||||
}
|
||||
if (trapno >= IRQ_OFFSET && trapno < IRQ_OFFSET + 16) {
|
||||
return "Hardware Interrupt";
|
||||
}
|
||||
return "(unknown trap)";
|
||||
}
|
||||
|
||||
/* trap_in_kernel - test if trap happened in kernel */
|
||||
bool
|
||||
trap_in_kernel(struct trapframe *tf) {
|
||||
return (tf->tf_cs == (uint16_t)KERNEL_CS);
|
||||
}
|
||||
|
||||
static const char *IA32flags[] = {
|
||||
"CF", NULL, "PF", NULL, "AF", NULL, "ZF", "SF",
|
||||
"TF", "IF", "DF", "OF", NULL, NULL, "NT", NULL,
|
||||
"RF", "VM", "AC", "VIF", "VIP", "ID", NULL, NULL,
|
||||
};
|
||||
|
||||
void
|
||||
print_trapframe(struct trapframe *tf) {
|
||||
cprintf("trapframe at %p\n", tf);
|
||||
print_regs(&tf->tf_regs);
|
||||
cprintf(" ds 0x----%04x\n", tf->tf_ds);
|
||||
cprintf(" es 0x----%04x\n", tf->tf_es);
|
||||
cprintf(" fs 0x----%04x\n", tf->tf_fs);
|
||||
cprintf(" gs 0x----%04x\n", tf->tf_gs);
|
||||
cprintf(" trap 0x%08x %s\n", tf->tf_trapno, trapname(tf->tf_trapno));
|
||||
cprintf(" err 0x%08x\n", tf->tf_err);
|
||||
cprintf(" eip 0x%08x\n", tf->tf_eip);
|
||||
cprintf(" cs 0x----%04x\n", tf->tf_cs);
|
||||
cprintf(" flag 0x%08x ", tf->tf_eflags);
|
||||
|
||||
int i, j;
|
||||
for (i = 0, j = 1; i < sizeof(IA32flags) / sizeof(IA32flags[0]); i ++, j <<= 1) {
|
||||
if ((tf->tf_eflags & j) && IA32flags[i] != NULL) {
|
||||
cprintf("%s,", IA32flags[i]);
|
||||
}
|
||||
}
|
||||
cprintf("IOPL=%d\n", (tf->tf_eflags & FL_IOPL_MASK) >> 12);
|
||||
|
||||
if (!trap_in_kernel(tf)) {
|
||||
cprintf(" esp 0x%08x\n", tf->tf_esp);
|
||||
cprintf(" ss 0x----%04x\n", tf->tf_ss);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_regs(struct pushregs *regs) {
|
||||
cprintf(" edi 0x%08x\n", regs->reg_edi);
|
||||
cprintf(" esi 0x%08x\n", regs->reg_esi);
|
||||
cprintf(" ebp 0x%08x\n", regs->reg_ebp);
|
||||
cprintf(" oesp 0x%08x\n", regs->reg_oesp);
|
||||
cprintf(" ebx 0x%08x\n", regs->reg_ebx);
|
||||
cprintf(" edx 0x%08x\n", regs->reg_edx);
|
||||
cprintf(" ecx 0x%08x\n", regs->reg_ecx);
|
||||
cprintf(" eax 0x%08x\n", regs->reg_eax);
|
||||
}
|
||||
|
||||
/* trap_dispatch - dispatch based on what type of trap occurred */
|
||||
static void
|
||||
trap_dispatch(struct trapframe *tf) {
|
||||
char c;
|
||||
|
||||
switch (tf->tf_trapno) {
|
||||
case IRQ_OFFSET + IRQ_TIMER:
|
||||
/* LAB1 YOUR CODE : STEP 3 */
|
||||
/* handle the timer interrupt */
|
||||
/* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
|
||||
* (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
|
||||
* (3) Too Simple? Yes, I think so!
|
||||
*/
|
||||
ticks ++;
|
||||
if (ticks % TICK_NUM == 0) {
|
||||
print_ticks();
|
||||
}
|
||||
break;
|
||||
case IRQ_OFFSET + IRQ_COM1:
|
||||
c = cons_getc();
|
||||
cprintf("serial [%03d] %c\n", c, c);
|
||||
break;
|
||||
case IRQ_OFFSET + IRQ_KBD:
|
||||
c = cons_getc();
|
||||
cprintf("kbd [%03d] %c\n", c, c);
|
||||
break;
|
||||
//LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
|
||||
case T_SWITCH_TOU:
|
||||
case T_SWITCH_TOK:
|
||||
panic("T_SWITCH_** ??\n");
|
||||
break;
|
||||
case IRQ_OFFSET + IRQ_IDE1:
|
||||
case IRQ_OFFSET + IRQ_IDE2:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
// in kernel, it must be a mistake
|
||||
if ((tf->tf_cs & 3) == 0) {
|
||||
print_trapframe(tf);
|
||||
panic("unexpected trap in kernel.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *
|
||||
* trap - handles or dispatches an exception/interrupt. if and when trap() returns,
|
||||
* the code in kern/trap/trapentry.S restores the old CPU state saved in the
|
||||
* trapframe and then uses the iret instruction to return from the exception.
|
||||
* */
|
||||
void
|
||||
trap(struct trapframe *tf) {
|
||||
// dispatch based on what type of trap occurred
|
||||
trap_dispatch(tf);
|
||||
}
|
||||
|
||||
91
labcodes_answer/lab2_result/kern/trap/trap.h
Normal file
91
labcodes_answer/lab2_result/kern/trap/trap.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef __KERN_TRAP_TRAP_H__
|
||||
#define __KERN_TRAP_TRAP_H__
|
||||
|
||||
#include <defs.h>
|
||||
|
||||
/* Trap Numbers */
|
||||
|
||||
/* Processor-defined: */
|
||||
#define T_DIVIDE 0 // divide error
|
||||
#define T_DEBUG 1 // debug exception
|
||||
#define T_NMI 2 // non-maskable interrupt
|
||||
#define T_BRKPT 3 // breakpoint
|
||||
#define T_OFLOW 4 // overflow
|
||||
#define T_BOUND 5 // bounds check
|
||||
#define T_ILLOP 6 // illegal opcode
|
||||
#define T_DEVICE 7 // device not available
|
||||
#define T_DBLFLT 8 // double fault
|
||||
// #define T_COPROC 9 // reserved (not used since 486)
|
||||
#define T_TSS 10 // invalid task switch segment
|
||||
#define T_SEGNP 11 // segment not present
|
||||
#define T_STACK 12 // stack exception
|
||||
#define T_GPFLT 13 // general protection fault
|
||||
#define T_PGFLT 14 // page fault
|
||||
// #define T_RES 15 // reserved
|
||||
#define T_FPERR 16 // floating point error
|
||||
#define T_ALIGN 17 // aligment check
|
||||
#define T_MCHK 18 // machine check
|
||||
#define T_SIMDERR 19 // SIMD floating point error
|
||||
|
||||
#define T_SYSCALL 0x80 // SYSCALL, ONLY FOR THIS PROJ
|
||||
|
||||
/* Hardware IRQ numbers. We receive these as (IRQ_OFFSET + IRQ_xx) */
|
||||
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
||||
|
||||
#define IRQ_TIMER 0
|
||||
#define IRQ_KBD 1
|
||||
#define IRQ_COM1 4
|
||||
#define IRQ_IDE1 14
|
||||
#define IRQ_IDE2 15
|
||||
#define IRQ_ERROR 19
|
||||
#define IRQ_SPURIOUS 31
|
||||
|
||||
/* *
|
||||
* These are arbitrarily chosen, but with care not to overlap
|
||||
* processor defined exceptions or interrupt vectors.
|
||||
* */
|
||||
#define T_SWITCH_TOU 120 // user/kernel switch
|
||||
#define T_SWITCH_TOK 121 // user/kernel switch
|
||||
|
||||
/* registers as pushed by pushal */
|
||||
struct pushregs {
|
||||
uint32_t reg_edi;
|
||||
uint32_t reg_esi;
|
||||
uint32_t reg_ebp;
|
||||
uint32_t reg_oesp; /* Useless */
|
||||
uint32_t reg_ebx;
|
||||
uint32_t reg_edx;
|
||||
uint32_t reg_ecx;
|
||||
uint32_t reg_eax;
|
||||
};
|
||||
|
||||
struct trapframe {
|
||||
struct pushregs tf_regs;
|
||||
uint16_t tf_gs;
|
||||
uint16_t tf_padding0;
|
||||
uint16_t tf_fs;
|
||||
uint16_t tf_padding1;
|
||||
uint16_t tf_es;
|
||||
uint16_t tf_padding2;
|
||||
uint16_t tf_ds;
|
||||
uint16_t tf_padding3;
|
||||
uint32_t tf_trapno;
|
||||
/* below here defined by x86 hardware */
|
||||
uint32_t tf_err;
|
||||
uintptr_t tf_eip;
|
||||
uint16_t tf_cs;
|
||||
uint16_t tf_padding4;
|
||||
uint32_t tf_eflags;
|
||||
/* below here only when crossing rings, such as from user to kernel */
|
||||
uintptr_t tf_esp;
|
||||
uint16_t tf_ss;
|
||||
uint16_t tf_padding5;
|
||||
} __attribute__((packed));
|
||||
|
||||
void idt_init(void);
|
||||
void print_trapframe(struct trapframe *tf);
|
||||
void print_regs(struct pushregs *regs);
|
||||
bool trap_in_kernel(struct trapframe *tf);
|
||||
|
||||
#endif /* !__KERN_TRAP_TRAP_H__ */
|
||||
|
||||
44
labcodes_answer/lab2_result/kern/trap/trapentry.S
Normal file
44
labcodes_answer/lab2_result/kern/trap/trapentry.S
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <memlayout.h>
|
||||
|
||||
# vectors.S sends all traps here.
|
||||
.text
|
||||
.globl __alltraps
|
||||
__alltraps:
|
||||
# push registers to build a trap frame
|
||||
# therefore make the stack look like a struct trapframe
|
||||
pushl %ds
|
||||
pushl %es
|
||||
pushl %fs
|
||||
pushl %gs
|
||||
pushal
|
||||
|
||||
# load GD_KDATA into %ds and %es to set up data segments for kernel
|
||||
movl $GD_KDATA, %eax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
|
||||
# push %esp to pass a pointer to the trapframe as an argument to trap()
|
||||
pushl %esp
|
||||
|
||||
# call trap(tf), where tf=%esp
|
||||
call trap
|
||||
|
||||
# pop the pushed stack pointer
|
||||
popl %esp
|
||||
|
||||
# return falls through to trapret...
|
||||
.globl __trapret
|
||||
__trapret:
|
||||
# restore registers from stack
|
||||
popal
|
||||
|
||||
# restore %ds, %es, %fs and %gs
|
||||
popl %gs
|
||||
popl %fs
|
||||
popl %es
|
||||
popl %ds
|
||||
|
||||
# get rid of the trap number and error code
|
||||
addl $0x8, %esp
|
||||
iret
|
||||
|
||||
1536
labcodes_answer/lab2_result/kern/trap/vectors.S
Normal file
1536
labcodes_answer/lab2_result/kern/trap/vectors.S
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user