静态定义的IDT [英] Statically Defined IDT

查看:100
本文介绍了静态定义的IDT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从事一个对启动时间有严格要求的项目.目标架构是在32位保护模式下运行的基于IA-32的处理器.可以改进的领域之一是当前系统动态初始化处理器的IDT(中断描述符表).由于我们没有任何即插即用设备,并且系统是相对静态的,因此我希望能够使用静态构建的IDT.

I'm working on a project that has tight boot time requirements. The targeted architecture is an IA-32 based processor running in 32 bit protected mode. One of the areas identified that can be improved is that the current system dynamically initializes the processor's IDT (interrupt descriptor table). Since we don't have any plug-and-play devices and the system is relatively static, I want to be able to use a statically built IDT.

但是,这对于IA-32拱门来说是麻烦的,因为8字节的中断门描述符会分割ISR地址. ISR的低16位出现在描述符的前2个字节中,其他一些位则填充在接下来的4个字节中,然后ISR的后16位最后出现在后2个字节中.

However, this proving to be troublesome for the IA-32 arch since the 8 byte interrupt gate descriptors splits the ISR address. The low 16 bits of the ISR appear in the first 2 bytes of the descriptor, some other bits fill in the next 4 bytes, and then finally the last 16 bits of the ISR appear in the last 2 bytes.

我想使用const数组定义IDT,然后像这样简单地将IDT寄存器指向它:

I wanted to use a const array to define the IDT and then simply point the IDT register at it like so:

typedef struct s_myIdt {
    unsigned short isrLobits;
    unsigned short segSelector;
    unsigned short otherBits;
    unsigned short isrHibits;
} myIdtStruct;

myIdtStruct myIdt[256] = {
    { (unsigned short)myIsr0, 1, 2, (unsigned short)(myIsr0 >> 16)},
    { (unsigned short)myIsr1, 1, 2, (unsigned short)(myIsr1 >> 16)},

这显然是行不通的,因为在C中这样做是非法的,因为myIsr不是常数.它的值由链接器(只能执行有限数量的数学运算)解析,而不由编译器解析.

Obviously this won't work as it is illegal to do this in C because myIsr is not constant. Its value is resolved by the linker (which can do only a limited amount of math) and not by the compiler.

关于如何执行此操作的任何建议或其他想法?

Any recommendations or other ideas on how to do this?

谢谢

推荐答案

您遇到了众所周知的x86疣.我不认为链接器可以IDT条目所期望的错位形式填充您的isr例程的地址.

You ran into a well known x86 wart. I don't believe the linker can stuff the address of your isr routines in the swizzled form expected by the IDT entry.

如果您有雄心壮志,则可以创建一个IDT构建器脚本,该脚本执行类似(基于Linux)方法的操作.我尚未测试过该方案,无论如何它都可能被认为是讨厌的黑客程序,因此请谨慎行事.

If you are feeling ambitious, you could create an IDT builder script that does something like this (Linux based) approach. I haven't tested this scheme and it probably qualifies as a nasty hack anyway, so tread carefully.

第1步:编写脚本以运行"nm"并捕获标准输出.

Step 1: Write a script to run 'nm' and capture the stdout.

第2步:在脚本中,解析nm输出以获取所有中断服务例程的内存地址.

Step 2: In your script, parse the nm output to get the memory address of all your interrupt service routines.

第3步:输出一个二进制文件'idt.bin',该文件的IDT字节已全部设置好,并准备好使用LIDT指令.您的脚本显然会以错误的正确格式输出isr地址.

Step 3: Output a binary file, 'idt.bin' that has the IDT bytes all setup and ready for the LIDT instruction. Your script obviously outputs the isr addresses in the correct swizzled form.

第4步:使用objcopy将其原始二进制文件转换为一个elf节:

Step 4: Convert his raw binary into an elf section with objcopy:

objcopy -I binary -O elf32-i386 idt.bin idt.elf

第5步:现在idt.elf文件具有IDT二进制文件,其符号如下所示:

Step 5: Now idt.elf file has your IDT binary with the symbol something like this:

> nm idt.elf
000000000000000a D _binary_idt_bin_end
000000000000000a A _binary_idt_bin_size
0000000000000000 D _binary_idt_bin_start

第6步:重新链接您的包含idt.elf的二进制文件.在程序集存根和链接描述文件中,您可以将符号_binary_idt_bin_start称为IDT的基础.例如,您的链接器脚本可以将符号_binary_idt_bin_start放在您喜欢的任何地址.

Step 6: relink your binary including idt.elf. In your assembly stubs and linker scripts, you can refer to symbol _binary_idt_bin_start as the base of the IDT. For example, your linker script can place the symbol _binary_idt_bin_start at any address you like.

请注意,与IDT部分重新链接不会移动二进制文件中的其他内容,例如您的isr例程.通过将IDT放在它自己的专用部分中,在链接描述文件(.ld文件)中进行管理.

Be careful that relinking with the IDT section doesn't move anyting else in your binary, e.g. your isr routines. Manage this in your linker script (.ld file) by puting the IDT into it's own dedicated section.

---编辑--- 从评论看,似乎对该问题感到困惑. 32位x86 IDT希望将中断服务程序的地址拆分为两个不同的16位字,如下所示:

---EDIT--- From comments, there seems to be confusion about the problem. The 32-bit x86 IDT expects the address of the interrupt service routine to be split into two different 16-bit words, like so:


 31           16 15            0
+---------------+---------------+
| Address 31-16 |               |
+---------------+---------------+
|               | Address 15-0  |
+---------------+---------------+

因此,链接器无法以正常的重定位方式插入ISR地址.因此,在启动时,软件必须构造此拆分格式,这会减慢启动时间.

A linker is thus unable to plug-in the ISR address as a normal relocation. So, at boot time, software must construct this split format, which slows boot time.

这篇关于静态定义的IDT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆