在bootsector.S中我们就打开了CR0寄存器的第0位(设置为1),即打开了保护模式。接下来进入今天的主题GDT(全局描述符表)的设置。首先来看下intel手册中是如何规定gdt的。

intel内置48位的GDTR寄存器,低16位代表描述符的数量,最大可有8192个描述符,基地址则规定了GDT表的地址。那么GDT表中的段描述符长啥样呢?可以从下图中窥见一斑。

那么根据这个段描述符的描述,总共8个字节,我们可以设定一个结构体来描述一个段描述符。本文主要借鉴ucore的GDT设置方法,如下所示:

gdt.h

gdt.c

到这里的时候其实已经完成gdt表的设置,但为了看到段描述符的变化,我们写一个打印函数来证明cs、ds等确实发生了变化。

到这里,GDT的设置就基本完成了,接下来进行IDT的配置。首先来看IDT表的结构,和GDT表的结构十分相似。

出现以下错误:

主要原因是.S文件中使用了.h中的一个变量,所以加了其头文件,但在编译的时候无法按.S格式解析.h文件中的结构体等,所以报错,改正如下

人为输入int 0x1中断,可以看到系统调用了1号中断服务程序,运行成功。至此,GDT和IDT的配置基本完成,代码如下:

gdt.c

#include "gdt.h"

/* *

* Global Descriptor Table:

*

* The kernel and user segments are identical (except for the DPL). To load

* the %ss register, the CPL must equal the DPL. Thus, we must duplicate the

* segments for the user and the kernel. Defined as follows:

* - 0x0 : unused (always faults -- for trapping NULL far pointers)

* - 0x8 : kernel code segment

* - 0x10: kernel data segment

* - 0x18: user code segment

* - 0x20: user data segment

* - 0x28: defined for tss, initialized in gdt_init

* */

static struct segdesc gdt[] = {

SEG_NULL, //null

SEG(STA_X | STA_R, 0x0, 0xFFFFFFFF, DPL_KERNEL), //kernel text

SEG(STA_W, 0x0, 0xFFFFFFFF, DPL_KERNEL), //kernel data

SEG(STA_X | STA_R, 0x0, 0xFFFFFFFF, DPL_USER), //user text

SEG(STA_W, 0x0, 0xFFFFFFFF, DPL_USER), //user data

SEG_NULL, //tss

};

/* *

* 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}};

//set gdt's info

static struct dtdesc gdtinfo={sizeof(gdt)-1,(unsigned int)gdt};

//set idt's info

static struct dtdesc idtinfo = {sizeof(idt) - 1, (unsigned int)idt};

/* *

* lgdt - load the global descriptor table register and reset the

* data/code segement registers for kernel.

* */

static inline void lgdt(struct dtdesc *dt)

{

asm volatile ("lgdt (%0)" :: "r" (dt));

asm volatile ("movw %%ax, %%gs" :: "a" (USER_DS));

asm volatile ("movw %%ax, %%fs" :: "a" (USER_DS));

asm volatile ("movw %%ax, %%es" :: "a" (KERNEL_DS));

asm volatile ("movw %%ax, %%ds" :: "a" (KERNEL_DS));

asm volatile ("movw %%ax, %%ss" :: "a" (KERNEL_DS));

// reload cs

asm volatile ("ljmp %0, $1f\n 1:\n" :: "i" (KERNEL_CS));

}

static inline void lidt(struct dtdesc *dt)

{

asm volatile ("lidt (%0)" :: "r" (dt) : "memory");

}

void gdt_init()

{

//load gdtinfo

lgdt(&gdtinfo);

}

void idt_init()

{

extern unsigned int __vectors[];

int i;

for (i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i ++) {

SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);

}

SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);

lidt(&idtinfo);

}

gdt.h

/* Application segment type bits */

#define STA_X 0x8 // Executable segment

#define STA_E 0x4 // Expand down (non-executable segments)

#define STA_C 0x4 // Conforming code segment (executable only)

#define STA_W 0x2 // Writeable (non-executable segments)

#define STA_R 0x2 // Readable (executable segments)

#define STA_A 0x1 // Accessed

/* global descrptor numbers */

#define GD_KTEXT ((1) << 3) // kernel text

#define GD_KDATA ((2) << 3) // kernel data

#define GD_UTEXT ((3) << 3) // user text

#define GD_UDATA ((4) << 3) // user data

#define GD_TSS ((5) << 3) // task segment selector

#define DPL_KERNEL (0)

#define DPL_USER (3)

//global descriptor selector

#define KERNEL_CS (GD_KTEXT|DPL_KERNEL)

#define KERNEL_DS (GD_KDATA|DPL_KERNEL)

#define USER_CS (GD_UTEXT|DPL_USER)

#define USER_DS (GD_UDATA|DPL_USER)

/* System segment type bits */

#define STS_CG32 0xC // 32-bit Call Gate

#define STS_IG32 0xE // 32-bit Interrupt Gate

#define STS_TG32 0xF // 32-bit Trap Gate

#define SEG_NULL \

(struct segdesc) {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

#define SEG(type, base, lim, dpl) \

(struct segdesc) { \

((lim) >> 12) & 0xffff, (base) & 0xffff, \

((base) >> 16) & 0xff, type, 1, dpl, 1, \

(unsigned)(lim) >> 28, 0, 0, 1, 1, \

(unsigned) (base) >> 24 \

}

#define SEGTSS(type, base, lim, dpl) \

(struct segdesc) { \

(lim) & 0xffff, (base) & 0xffff, \

((base) >> 16) & 0xff, type, 0, dpl, 1, \

(unsigned) (lim) >> 16, 0, 0, 1, 0, \

(unsigned) (base) >> 24 \

}

#define T_SYSCALL 0x80

/* *

* Set up a normal interrupt/trap gate descriptor

* - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate

* - sel: Code segment selector for interrupt/trap handler

* - off: Offset in code segment for interrupt/trap handler

* - dpl: Descriptor Privilege Level - the privilege level required

* for software to invoke this interrupt/trap gate explicitly

* using an int instruction.

* */

#define SETGATE(gate, istrap, sel, off, dpl) { \

(gate).gd_off_15_0 = (unsigned int)(off) & 0xffff; \

(gate).gd_ss = (sel); \

(gate).gd_args = 0; \

(gate).gd_rsv1 = 0; \

(gate).gd_type = (istrap) ? STS_TG32 : STS_IG32; \

(gate).gd_s = 0; \

(gate).gd_dpl = (dpl); \

(gate).gd_p = 1; \

(gate).gd_off_31_16 = (unsigned int)(off) >> 16; \

}

/* segment descriptors */

//bit field

struct segdesc{

unsigned sd_lim_15_0 : 16; // low bits of segment limit

unsigned sd_base_15_0 : 16; // low bits of segment base address

unsigned sd_base_23_16 : 8; // middle bits of segment base address

unsigned sd_type : 4; // segment type (see STS_ constants)

unsigned sd_s : 1; // 0 = system, 1 = application

unsigned sd_dpl : 2; // descriptor Privilege Level

unsigned sd_p : 1; // present

unsigned sd_lim_19_16 : 4; // high bits of segment limit

unsigned sd_avl : 1; // unused (available for software use)

unsigned sd_rsv1 : 1; // reserved

unsigned sd_db : 1; // 0 = 16-bit segment, 1 = 32-bit segment

unsigned sd_g : 1; // granularity: limit scaled by 4K when set

unsigned sd_base_31_24 : 8; // high bits of segment base address

};

/* Gate descriptors for interrupts and traps */

struct gatedesc {

unsigned gd_off_15_0 : 16; // low 16 bits of offset in segment

unsigned gd_ss : 16; // segment selector

unsigned gd_args : 5; // # args, 0 for interrupt/trap gates

unsigned gd_rsv1 : 3; // reserved(should be zero I guess)

unsigned gd_type : 4; // type(STS_{TG,IG32,TG32})

unsigned gd_s : 1; // must be 0 (system)

unsigned gd_dpl : 2; // descriptor(meaning new) privilege level

unsigned gd_p : 1; // Present

unsigned gd_off_31_16 : 16; // high bits of offset in segment

};

//describe the gdt/ldt/idt,remember struct's member is first member in low address

struct dtdesc{

unsigned short dt_size;

unsigned int dt_base;

}__attribute__((packed));

static inline void lgdt(struct dtdesc *dt);

static inline void lidt(struct dtdesc *dt);

void lidt(struct dtdesc *dt);

void gdt_init();

void idt_init();

trap.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

/* 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 {

unsigned int reg_edi;

unsigned int reg_esi;

unsigned int reg_ebp;

unsigned int reg_oesp; /* Useless */

unsigned int reg_ebx;

unsigned int reg_edx;

unsigned int reg_ecx;

unsigned int reg_eax;

};

struct trapframe {

struct pushregs tf_regs;

unsigned short tf_gs;

unsigned short tf_padding0;

unsigned short tf_fs;

unsigned short tf_padding1;

unsigned short tf_es;

unsigned short tf_padding2;

unsigned short tf_ds;

unsigned short tf_padding3;

unsigned int tf_trapno;

/* below here defined by x86 hardware */

unsigned int tf_err;

unsigned int tf_eip;

unsigned short tf_cs;

unsigned short tf_padding4;

unsigned int tf_eflags;

/* below here only when crossing rings, such as from user to kernel */

unsigned int tf_esp;

unsigned short tf_ss;

unsigned short tf_padding5;

} __attribute__((packed));

static void trap_dispatch(struct trapframe *tf);

void trap(struct trapframe *tf);

trap.h

#include "trap.h"

#include "vga.h"

/* *

* 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.

* */

/* trap_dispatch - dispatch based on what type of trap occurred */

static void trap_dispatch(struct trapframe *tf)

{

char c;

switch (tf->tf_trapno) {

case 1:

print_string("interrupt 1!\n",black,green);

break;

case IRQ_OFFSET + IRQ_TIMER:

break;

case IRQ_OFFSET + IRQ_COM1:

break;

case IRQ_OFFSET + IRQ_KBD:

break;

case T_SWITCH_TOU:

break;

case T_SWITCH_TOK:

break;

case IRQ_OFFSET + IRQ_IDE1:

case IRQ_OFFSET + IRQ_IDE2:

/* do nothing */

break;

default:

// in kernel, it must be a mistake

print_string("unexpected trap in kernel!\n",black,green);

}

}

void trap(struct trapframe *tf)

{

// dispatch based on what type of trap occurred

trap_dispatch(tf);

}

运行结果:

参考资料:

1.ucore操作系统

2.http://wiki.0xffffff.org/posts/hurlex-7.html

三、GDT和IDT的配置相关推荐

  1. CPU实模式和保护模式、全局描述符表GDT、Linux内核中GDT和IDT的结构定义

    一 计算机实模式和保护模式 实模式 在实模式下,内存被限制为仅有1M字节(220 字节).有效的地址从00000到FFFFF (十六进制). 这些地址需要用20位的数来表示.一个20位的数不适合任何一 ...

  2. DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描...

    DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载    系列目录连接 DB数据源之Spr ...

  3. Kinect开发学习笔记之(三)Kinect开发环境配置

    Kinect开发学习笔记之(三)Kinect开发环境配置 zouxy09@qq.com http://blog.csdn.net/zouxy09 我的Kinect开发平台是: Win7 x86 + V ...

  4. [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBuild+GitHub)

    本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...

  5. 华三H3C交换机路由器如何配置dhcp中继

    华三H3C交换机路由器如何配置dhcp中继(dhcp relay) 华三交换机路由器如何配置dhcp中继(dhcp relay) 具体环境如上图,内网有专门的dhcp服务器(此处用华三路由器代替)连接 ...

  6. 计算机网络与协议实验VLAN配置,计算机网络实验三虚拟局域网vlan划分与配置

    计算机网络实验三虚拟局域网vlan划分与配置 (5页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 计算机网络原理计算机网络原理 实验报告 ...

  7. 华三模拟器HCL安装与配置-关联piped、SecureCRT、Wireshark

    华三模拟器HCL安装与配置-关联piped.SecureCRT.Wireshark 目录 一. 华三模拟器介绍- 2 1.1 概述- 2 1.2 HCL简介- 2 1.3 HCL模拟器 V2.1.1说 ...

  8. win7 x64驱动开发经验(三)windbg 双机调试配置 、问题及解决办法

    win7 x64驱动开发经验(三)windbg 双机调试配置 .问题及解决办法 http://www.cnblogs.com/witty/archive/2012/04/23/2466024.html ...

  9. steam游戏上架流程三: 游戏的发布配置与测试

    参考: steamworks.net 官方文档的说明 http://steamworks.github.io/gettingstarted/ steam游戏上架流程一:使用官方SDK上传游戏  htt ...

  10. mysql配置数据库连接池_三种数据库连接池的配置

    三种数据库连接池的配置及使用(For JDBC) 连接池的优缺点 优点 使用连接池的最主要的优点是性能.创建一个新的数据库连接所耗费的时间主要取决于网络的速 度以及应用程序和数据库服务器的 ( 网络 ...

最新文章

  1. keras构建前馈神经网络(feedforward neural network)进行分类模型构建基于早停法(Early stopping)
  2. 工资高低由什么决定?(面试时如何谈工资?工作中怎样做才能不断涨工资?)...
  3. 【 MATLAB 】信号处理工具箱之波形产生函数 rectpuls
  4. Salesforce - soql 多字段多值过滤查询思路
  5. Activity中与ListActivity中使用listview区别
  6. 用nodejs搭建最简单、轻量化的http server
  7. 【渝粤题库】国家开放大学2021春1080工程数学(本)题目
  8. UBUNTU下双显示器设置
  9. C++经典问题:如果对象A中有对象成员B,对象B没有默认构造函数,那么对象A必须在初始化列表中初始化对象B?
  10. 乐山市计算机学校太坑,乐山市计算机学校小规矩成就大素养
  11. 百度UEditor编辑器使用(二)
  12. Modbus RTU CRC校验码计算方法
  13. IDL 读取葵花8(Himawari-8)HSD数据
  14. 《禅者的初心》读书笔记(2)
  15. linux下检查磁盘是否有坏道,badblocks 检查硬盘是否有坏道
  16. 【USACO3-4-2】电网 皮克定理
  17. 增量迭代模型,瀑布模型,螺旋模型,快速原型模型
  18. 八大常用基础电路保护器件作用
  19. 解决:win10下修改mac地址的方法
  20. 三种求平方根的算法——C/C++

热门文章

  1. hexo写博客时怎么插入图片
  2. 江苏省人力资源社会保障厅 省职称办 关于做好2021年度职称评审工作的通知
  3. DevC++和ege19.01版本图形库的配置安装
  4. Windows图片和传真查看器修复办法
  5. 山地车中轴进水表现_山地车中轴异响分析及解决方法
  6. 服务器虚拟内存可以设置其他盘,Win7系统如何把虚拟内存设置在其它盘符?
  7. Python高级教程
  8. DCT--离散余弦变换
  9. 实施ERP系统需要注意哪些方面?
  10. 计算前复权和后复权价格?A股复权因子的使用