Linux 0.12 OS. math - CR0
2013-05-10 22:38
459 查看
从这篇文章开始算是正式进入math模块的学习,前期我花了大量的时间来储备必要的知识,这个工作早在今年年初就进行了,可是被各种原因耽搁,我也寄希望于接下来能顺利进行。
这里得说一下,我是一边学习一边做的笔记,因此非常大可能出现错误。如果在文章发表后发现错误,我会及时更新上去,希望尽可能不给大家的理解造成困扰。
一 CR0控制寄存器
- NE
浮点处理器操作模式,0为MS-DOS compatibility mode(Vector 45, IRQ13),1为Native mode(Vector 16, Coprocessor error)。
- ET (Extension Type)
协处理器类型,0表示80287协处理器或者没有协处理器,1表示80387协处理器。
- TS (Task Switched)
任务已切换标志,0表示任务没有被切换,1表示任务已切换成功。它可以延迟保存任务切换时协处理器的内容(系统通过触发一个DNA(Device Not Available, Vector 7, device not available)异常来让你保存任务切换时协处理器的内容),直到新任务开始执行协处理器指令。一个直观的事实是如果新任务一直没有执行协处理器指令,那么保存之前任务的协处理器内容的操作就会一直被延迟,试想,如果在切回原任务前都没有任务执行协处理器指令,那么当前的协处理器内容就是原任务协处理器的内容,省去了协处理器内容的互换操作。
- EM (EMulation)
仿真标志,0表示系统有协处理器,1表示系统没有协处理器。对于EM和TS,EM=1系统没有协处理器或者EM=0 & TS=1任务已切换,一旦遇到协处理器指令就会触发DNA异常。
- MP (Math Present)
协处理器监控标志,0表示不监控,1表示开始监控。对于MP和TS,MP=1 & TS=1任务已切换被监控到,一旦遇到WAIT or FWAIT指令就会触发DNA异常。
二 Code部分
- boot/head.s (check x87)
- kernel/asm.s (IRQ13)
- kernel/sys_call.s (Coprocessor error)
- kernel/sys_call.s (Device Not Available)
- include/linux/sched.h (Task Switched)
这里得说一下,我是一边学习一边做的笔记,因此非常大可能出现错误。如果在文章发表后发现错误,我会及时更新上去,希望尽可能不给大家的理解造成困扰。
一 CR0控制寄存器
- NE
浮点处理器操作模式,0为MS-DOS compatibility mode(Vector 45, IRQ13),1为Native mode(Vector 16, Coprocessor error)。
- ET (Extension Type)
协处理器类型,0表示80287协处理器或者没有协处理器,1表示80387协处理器。
- TS (Task Switched)
任务已切换标志,0表示任务没有被切换,1表示任务已切换成功。它可以延迟保存任务切换时协处理器的内容(系统通过触发一个DNA(Device Not Available, Vector 7, device not available)异常来让你保存任务切换时协处理器的内容),直到新任务开始执行协处理器指令。一个直观的事实是如果新任务一直没有执行协处理器指令,那么保存之前任务的协处理器内容的操作就会一直被延迟,试想,如果在切回原任务前都没有任务执行协处理器指令,那么当前的协处理器内容就是原任务协处理器的内容,省去了协处理器内容的互换操作。
- EM (EMulation)
仿真标志,0表示系统有协处理器,1表示系统没有协处理器。对于EM和TS,EM=1系统没有协处理器或者EM=0 & TS=1任务已切换,一旦遇到协处理器指令就会触发DNA异常。
- MP (Math Present)
协处理器监控标志,0表示不监控,1表示开始监控。对于MP和TS,MP=1 & TS=1任务已切换被监控到,一旦遇到WAIT or FWAIT指令就会触发DNA异常。
二 Code部分
- boot/head.s (check x87)
/* * NOTE! 486 should set bit 16, to check for write-protect in supervisor * mode. Then it would be unnecessary with the "verify_area()"-calls. * 486 users probably want to set the NE (#5) bit also, so as to use * int 16 for math errors. */ movl %cr0,%eax # check math chip andl $0x80000011,%eax # Save PG,PE,ET, reset NE,TS,EM,MP /* "orl $0x10020,%eax" here for 486 might be good */ orl $2,%eax # set MP movl %eax,%cr0 call check_x87 jmp after_page_tables /* * We depend on ET to be correct. This checks for 287/387. */ check_x87: fninit /* initialize swd,cwd,twd */ fstsw %ax /* store swd to ax register, all is 0 except for that the condition code of swd is indeterminte */ cmpb $0,%al /* 如果al为0(al初始不为0),则表示协处理器有将swd初始化 */ je 1f /* no coprocessor: have to set bits */ movl %cr0,%eax xorl $6,%eax /* reset MP, set EM , 此时EM=1,没有协处理器,MP=0,不会监控TS标志 */ movl %eax,%cr0 ret .align 4 1: .byte 0xDB,0xE4 /* fnsetpm(not 'fsetpm') for 287, ignored by 387,对于80287需要设定为保护模式 */ ret
- kernel/asm.s (IRQ13)
irq13: pushl %eax xorb %al,%al outb %al,$0xF0 /* 0xF0是协处理器端口,用于清忙锁存器 */ movb $0x20,%al outb %al,$0x20 /* 向8259主中断控制器发送EOI(中断结束)信号 */ jmp 1f 1: jmp 1f 1: outb %al,$0xA0 /* 向8259从中断控制器发送EOI(中断结束)信号 */ popl %eax jmp coprocessor_error /* 异常转移 */
- kernel/sys_call.s (Coprocessor error)
coprocessor_error: /* 目前没有任何功能 */ push %ds push %es push %fs pushl $-1 # fill in -1 for orig_eax pushl %edx pushl %ecx pushl %ebx pushl %eax movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs pushl $ret_from_sys_call jmp math_error
- kernel/sys_call.s (Device Not Available)
device_not_available: /* '大名鼎鼎'的DNA异常 */ push %ds push %es push %fs pushl $-1 # fill in -1 for orig_eax pushl %edx pushl %ecx pushl %ebx pushl %eax movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs pushl $ret_from_sys_call /* 以上为标准的system call writing */ clts /* clear TS so that we can use math, 注意TS只在EM=0时才有意义 */ movl %cr0,%eax testl $0x4,%eax # EM (math emulation bit) je math_state_restore /* EM=0表示系统有协处理器,那么按正常flow跑即可,去执行协处理器内容的互换操作 */ pushl %ebp pushl %esi pushl %edi pushl $0 # temporary storage for ORIG_EIP call math_emulate /* 看来系统没有协处理器,开始协处理器的模拟 */ addl $4,%esp popl %edi popl %esi popl %ebp ret
- include/linux/sched.h (Task Switched)
/* * switch_to(n) should switch tasks to task nr n, first * checking that n isn't the current task, in which case it does nothing. * This also clears the TS-flag if the task we switched to has used * tha math co-processor latest. */ #define switch_to(n) {\ struct {long a,b;} __tmp; \ __asm__("cmpl %%ecx,current\n\t" \ "je 1f\n\t" \ "movw %%dx,%1\n\t" \ "xchgl %%ecx,current\n\t" \ "ljmp *%0\n\t" \ "cmpl %%ecx,last_task_used_math\n\t" \ /* 如果说返回原任务前没有其他任务去执行协处理器指令,那么清掉TS标志,无需进行协处理器内容的互换操作 */ "jne 1f\n\t" \ "clts\n" \ "1:" \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ "d" (_TSS(n)),"c" ((long) task )); \ }
相关文章推荐
- Linux 0.12 OS. math - math_emulate.c
- Linux 0.12 OS. math - error.c
- Linux 0.12 OS. math - math_emu.h
- Linux 0.12 OS. math - ea.c
- Linux 0.12 OS. math - convert.c
- Linux 0.12 OS. math - get_put.c
- Linux 0.12 OS. math - add.c
- Linux 0.12 OS. math - mul.c
- Linux 0.12 OS. math - div.c
- Linux 0.12 OS. math - compare.c
- Linux 0.12 OS. block - blk.h
- Linux 0.12 OS. block - ll_rw_blk.c
- 系统程序Linux启动过程前传——前世BIOS与今生OS
- linux或者UC/OS
- Boot The Cortex-A9 MPCORE With Linux+uC/OS-II AMP
- Linux/Unix/Mac OS下的远程访问和文件共享方式
- OS: 脏牛(Dirty COW)漏洞:Linux 内核通杀提权漏洞 (CVE-2016-5195)
- 如何移植uCOS-III到Linux系统 How to Port uCOS-III on Linux OS
- Linux R Server: Error [tcl] unknown math function "min".
- uC/OS-II、eCos、Linux的简要比较