x86/x86_64处理器提供了4个内存管理寄存器(Memory Management Registers):GDTR、LDTR、IDTR和TR。如下图所示。 Global Descriptor Table Register(GDTR) GDTR寄存器保存GDT的基址和表限(table limit)。基址是GDT的第一个字节的地址,表限(table limit)给出表的大小。 指令LGDT和SGDT是分别用来设置和保存GDTR寄存器的值。上电或重启处理器后,基址默认的值为0,表限(table limit)的值为0FFFFH。在保护模式运行前,作为处理器初始化的一部分,必须在GDTR寄存器中设置新的基址。 在Linux地址映射过程中,会用到GDTR寄存器。在此稍微详细介绍一下指令SGDT,即获取GDTR寄存器的值。SGDT指令的操作如下: Operation IF instruction is SGDT IF OperandSize = 16 THEN DEST[0:15] ← GDTR(Limit); DEST[16:39] ← GDTR(Base); (* 24 bits of base address stored *) DEST[40:47] ← 0; ELSE IF (32-bit Operand Size) DEST[0:15] ← GDTR(Limit); DEST[16:47] ← GDTR(Base); (* Full 32-bit […]
READ MORE »Posts in category 内核基础
x86/x86_64 CPU控制寄存器(Control Registers)
x86/x86_64 CPU中提供了控制寄存器,来决定CPU的操作模式和当前执行任务的属性。这些寄存器在32位模式下是32bit,在64位模式中,控制寄存器扩展为64位。 CPU架构中共有CR0、CR1、CR2、CR3、CR4、CR8共6个控制寄存器,如下图。 各个控制寄存器的作用如下: CR0:包含当前处理器运行的控制标志。 CR1:保留。 CR2:包含发生页面错误时的线性地址。 CR3:页面目录表(Page Directory Table)的物理地址。 CR4:包含处理器扩展功能的标志位。 CR8:提供对任务优先级寄存器(Task Priority Register)的读写(仅在64位模式下存在)。 对控制寄存器的读写是通过MOV CRn指令来实现 下面代码(注意:本源码是32位系统)可用来读取CRn控制寄存器的值。 #include <linux/module.h> #include <linux/proc_fs.h> static char modname[] = “cr4″; static int cr4; static int my_get_info( char *buf, char **start, off_t off, int count ) { int len = 0; asm(” movl %cr4, %ebx \n movl %ebx, cr4 “); […]
READ MORE »Linux内核模块加载报错”no symbol version for struct_module”解决办法
编译iscsi_trgt内核模块后,加载模块失败,提示“Invalid module format“,通过dmesg看到内核打印“no symbol version for struct_module“。 [root@xenserver-chen iscsitarget-1.4.20.2]# insmod /root/iscsitarget-1.4.20.2/kernel/iscsi_trgt.ko insmod: error inserting ‘/root/iscsitarget-1.4.20.2/kernel/iscsi_trgt.ko’: -1 Invalid module format
READ MORE »Linux内核死锁(deadlock)检测
业务运行过程中,Linux系统僵死,屏幕无任何有效打印信息,网络中断、键盘鼠标没有任何响应。这种故障现象,可能是因为Linux内核死锁导致。由于无任何有效打印信息,内核日志中也没有记录,就无法定位故障根因。 如何让Linux内核在僵死前打印相关信息,对问题定位尤为关键。其中一个有效手段是打开“Kernel Hacking”选项,然后重新编译内核。 对于Linux内核死锁有帮助的几个配置选项有: [*] Detect Soft Lockups [ ] Panic (Reboot) On Soft Lockups [*] Detect Hung Tasks (120) Default timeout for hung task detection (in seconds) [*] Panic (Reboot) On Hung Tasks [ ] Lock usage statistics [ ] Spinlock debugging: sleep-inside-spinlock checking 下面一个实例是在SLES11.1 2.6.32.12-0.7内核中系统僵死前,检测到内核死锁并panic,打印出了死锁进程和信息。 ftp D ffff88010d7c5978 4472 22481 […]
READ MORE »Linux PCI Express配置空间读写内核实现
在x86/x86_64 CPU中PCI Express扩展配置空间访问 中,我们分析了PCI-E配置空间是如何映射到物理内存地址空间的。 本文介绍Linux内核是如何读写PCI/PCI-E配置空间,包括传统PCI设备256字节配置空间的访问,和PCI-E扩展配置空间如何访问。 点击阅读详细内容
READ MORE »Linux内核空间与用户空间
内核空间(Kernel Space)与用户空间(User Space) 内核空间可以访问所有的CPU指令和所有的内存空间、I/O空间。 用户空间只能访问有限的资源,若需要特殊权限,可以通过系统调用获取相应的资源。 用户空间允许页面中断,而内核空间则不允许。 x86 CPU中用户空间是0-3G的地址范围,内核空间是3G-4G的地址范围。x86_64 CPU用户空间地址范围为0x0000000000000000 – 0x00007fffffffffff,内核地址空间为0xffff880000000000~最大地址。 内核空间和用户空间是针对线性地址空间的。 所有内核进(线)程共用一个地址空间,而用户进程都有各自的地址空间。
READ MORE »x86/x86_64 CPU中PCI Express扩展配置空间访问
PCI Express配置空间 PCI-E是用来互联如计算和通信平台应用中外围设备的第三代高性能I/O总线。PCI-E采用了与PCI相同的使用模型和读写(load-store)通信模型,支持各种常见的事务,如存储器读/写、IO读/写和配置读/写事务。其存储器、IO和配置地址空间与PCI的地址空间相同。PCI Express与PCI系统是软件向后兼容的。
READ MORE »Linux内核死机与栈信息理解
在Linux内核死机或内核打印异常栈信息时,这些打印的含义是什么?下面作一个简单解释。 Oops: 0002 [1] SMP CPU 3 Pid: 19394, comm: stress Tainted: GF U (2.6.5-7.244-smp SLES9_SP3_BRANCH-200512121832250000) RIP: 0010:[<ffffffff8016e5ad>] <ffffffff8016e5ad>{free_block+237} Oops:表示当前内核故障类型 002:页面错误码,表示内核试图写一个不存在的页面 [1]:死机计数器,记录册从上次系统重启以来的死机次数 CPU:表示系统运行故障时所在的CPU Pid:系统故障时,运行的进程 RIP:系统故障时,执行的指令位置
READ MORE »Linux CPU利用率计算原理及内核实现
我们经常使用top命令来查看CPU利用率,如 root@ubuntu:~# top top – 09:16:29 up 6 min, 4 users, load average: 0.01, 0.22, 0.17 Tasks: 149 total, 1 running, 147 sleeping, 0 stopped, 1 zombie Cpu(s): 2.8%us, 6.7%sy, 0.2%ni, 89.9%id, 0.3%wa, 0.0%hi, 0.1%si, 0.0%st Mem: 508000k total, 404092k used, 103908k free, 47764k buffers Swap: 522236k total, 0k used, 522236k free, 184992k cached PID […]
READ MORE »Linux读写CPU MSR寄存器命令rdmsr/wrmsr
在Linux内核源码中提供了读写CPU MSR寄存器模块,使可以在用户空间直接读写MSR寄存器。 开源社区提供msr寄存器读写工具msrtools,其中有两个命令,rdmsr/wrmsr。要使rdmsr/wrmsr命令真正可以读写msr寄存器,系统中必须有msr模块,或将msr模块编译进内核,下面是从内核配置选项中选取的内容。 Processor type and features —> <M> /dev/cpu/*/msr – Model-specific register support 实例: root@ubuntu:~/linux-2.6.32.36-0.5# rdmsr 0x1a0 0 root@ubuntu:~/linux-2.6.32.36-0.5# rdmsr和wrmsr命令格式如下: root@ubuntu:~# rdmsr Usage: rdmsr [options] regno –help -h Print this help –version -V Print current version –hexadecimal -x Hexadecimal output (lower case) –capital-hex -X Hexadecimal output (upper case) –decimal -d Signed decimal output –unsigned […]
READ MORE »