[vox-tech] Fwd: Implementing interrupt handlers
Brian Lavender
brian at brie.com
Fri Dec 23 14:46:04 PST 2011
Immediate thoughts that I can think follow.
Do you have to put in an address in a register to handle your
interrupt? The reason I wonder is that it appears that it complains that
EIP is invalid. I take it the value for EIP is jumping somewhere where
the kernel knows it shouldn't be or the MMU is faulting it (you don't
have a valid page there). If I understand you correctly, you are writing
your own system call. Isn't that the equivalent of a software interrupt?
brian
On Tue, Dec 20, 2011 at 06:25:46PM -0800, Bill Kendrick wrote:
>
> David posted this from an address that's not subscribed to the list.
> Fwd'ing on his behalf.
>
> -bill!
>
>
> ----- Forwarded message from vox-tech-bounces at lists.lugod.org -----
>
> Date: Tue, 20 Dec 2011 08:03:54 -0800
> From: vox-tech-bounces at lists.lugod.org
> Subject: Auto-discard notification
> To: vox-tech-owner at lists.lugod.org
>
> The attached message has been automatically discarded.
> Date: Tue, 20 Dec 2011 15:57:23 +0000
> From: David Luengo López <olelen at gmail.com>
> Subject: Implementing interrupt handlers
> To: vox-tech at lists.lugod.org
>
> Hi everyone, let's see if you can help me.
>
> I'm trying to implement my own interrupt handler (why? because it's fun
> :). My idea right now is to install on the system a function like
> system_call() (you know, the handler of int $0x80), but on a free
> interrupt.
>
> First I tried by using the kernel function request_irq(), but when I look
> at the corresponding IDT entry there still was the ignore_int() function
> (you know, Linux sets all the interrupt handlers as ignore_int() and then
> it fills the handlers properly with ?init_traps()?). Am I wrong or should
> request_irq() write on IDT?.
>
> After failing with request_irq() I decided to write the changes on IDT by
> my own, so right now the changes on IDT are made by me (using a bit of
> kernel's help):
>
> /***
> * @n: The index on the IDT that should be rewritten.
> * @addr: The address of the new interrupt handler.
> */
> void setGate(unsigned int n, unsigned long addr) {
> gate_desc entry, *idt;
> struct desc_ptr idtr;
>
> // Code extracted from arch/x86/include/asm/desc.h, I prefer to have
> the
> // same notation.
> entry.a = (__KERNEL_CS << 16) | (addr & 0xffff);
> entry.b = (addr & 0xffff0000) |
> ((0x80 | (RING3 << 5) | GATE_TRAP) << 8) |
> 0x00;
>
> native_store_idt(&idtr);
> idt = (gate_desc *)idtr.address;
> native_write_idt_entry(idt, n, &entry);
> }
>
> Here we have not the includes and defines needed but it is not hard to
> guess them (<asm/desc.h>, <asm/desc_defs.h>, define RING3 (3) if I still
> remember...).
>
> When I do it by my own the IDT is correctly rewritten but when i try to
> call that interrupt from user space context i got an error. Here you have
> the stupid program that generates the interrupt:
>
> .globl main
> main:
> int $<n>
> nop
>
> Where <n> is the vector of the interrupt I rewrote, usually interrupt 31.
>
> When I run this program the task got killed and the kernel wrote this
> message into /var/log/messages:
>
> ...: [17234.280005] *pde = 1d9dc067 *pte = 00000000
> ...: [17234.280005] Modules linked in: yarr loop snd_ens1371 gameport
> snd_rawmidi snd_seq_device snd_ac97_codec ac97_bus snd_pcm snd_timer snd
> i2c_piix4 soundcore shpchp snd_page_alloc pci_hotplug i2c_core parport_pc
> psmouse parport pcspkr serio_raw evdev container processor ac button ext3
> jbd mbcache sg sd_mod crc_t10dif sr_mod cdrom uhci_hcd ata_generic mptspi
> mptscsih ata_piix ehci_hcd mptbase libata thermal floppy pcnet32 mii
> usbcore nls_base scsi_transport_spi scsi_mod thermal_sys [last unloaded:
> yarr]
> ...: [17234.280005]
> ...: [17234.280005] Pid: 1772, comm: intr_poc Tainted: G D W
> (2.6.32-5-686 #1) VMware Virtual Platform
> ...: [17234.280005] EIP: 0060:[<e0ea32e9>] EFLAGS: 00010246 CPU: 0
> ...: [17234.280005] EIP is at 0xe0ea32e9
> ...: [17234.280005] EAX: bffffdf4 EBX: b7fd7ff4 ECX: 261e90fa EDX:
> 00000001
> ...: [17234.280005] ESI: 00000000 EDI: 00000000 EBP: bffffdc8 ESP:
> dfa55fe4
> ...: [17234.280005] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068
> ...: [17234.280005] 08048396 00000073 00000246 bffffd4c 0000007b 00000000
> 00000000
> ...: [17234.280005] ---[ end trace 323827b587f0e55d ]---
>
> And also this to dmesg:
> [17234.280005] BUG: unable to handle kernel paging request at e0ea32e9
> [17234.280005] IP: [<e0ea32e9>] 0xe0ea32e9
> [17234.280005] *pde = 1d9dc067 *pte = 00000000
> [17234.280005] Oops: 0000 [#2] SMP
> [17234.280005] last sysfs file: /sys/devices/virtual/net/lo/operstate
> [17234.280005] Modules linked in: yarr loop snd_ens1371 gameport
> snd_rawmidi snd_seq_device snd_ac97_codec ac97_bus snd_pcm snd_timer snd
> i2c_piix4 soundcore shpchp snd_page_alloc pci_hotplug i2c_core parport_pc
> psmouse parport pcspkr serio_raw evdev container processor ac button ext3
> jbd mbcache sg sd_mod crc_t10dif sr_mod cdrom uhci_hcd ata_generic mptspi
> mptscsih ata_piix ehci_hcd mptbase libata thermal floppy pcnet32 mii
> usbcore nls_base scsi_transport_spi scsi_mod thermal_sys [last unloaded:
> yarr]
> [17234.280005]
> [17234.280005] Pid: 1772, comm: intr_poc Tainted: G D W
> (2.6.32-5-686 #1) VMware Virtual Platform
> [17234.280005] EIP: 0060:[<e0ea32e9>] EFLAGS: 00010246 CPU: 0
> [17234.280005] EIP is at 0xe0ea32e9
> [17234.280005] EAX: bffffdf4 EBX: b7fd7ff4 ECX: 261e90fa EDX: 00000001
> [17234.280005] ESI: 00000000 EDI: 00000000 EBP: bffffdc8 ESP: dfa55fe4
> [17234.280005] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068
> [17234.280005] Process intr_poc (pid: 1772, ti=dfa54000 task=df818000
> task.ti=dfa54000)
> [17234.280005] Stack:
> [17234.280005] 08048396 00000073 00000246 bffffd4c 0000007b 00000000
> 00000000
> [17234.280005] Call Trace:
> [17234.280005] Code: Bad EIP value.
> [17234.280005] EIP: [<e0ea32e9>] 0xe0ea32e9 SS:ESP 0068:dfa55fe4
> [17234.280005] CR2: 00000000e0ea32e9
> [17234.280005] ---[ end trace 323827b587f0e55d ]---
>
> I have written with bold font those things that makes me think.
>
> Yarr is the name of my module and intr_poc the program that makes int
> $<n>. When I check the IDT to look the address of the interrupt handler I
> have installed I obtain the address of the function that I want to be my
> interrupt handler. I checked it against /proc/kallsyms, where the symbols
> of my module are. This function is just this:
>
> static irqreturn_t yarrIntrDesc(int irq, void *dev_id) {
> printk("YARR! WE ARE MIGHTY PIRATES!\n");
> return IRQ_RETVAL(0);
> }
>
> And the symbols of my module are these:
>
> $ egrep "yarr" /proc/kallsyms
> e0eae2e9 t yarrIntrDesc [yarr]
> ...
>
> We can observe that the EIP is near this function (it fails not at the
> beginning but in the middle of the function, so it enters here...).
>
> We can see in dmesg's message that "Bad EIP value", and also a line
> talking about pde and pte. PTE is the Page Table Entry and PDE in fact a
> pmd_t structure which takes part of the kernel when we have more than 2
> levels of page indexing.
>
> I'm thinking about page permissions since there are references to PTE
> (with an impressive value of 0). Another thing that makes me look at it is
> the distance between my interrupt handler (e0eae2e9) and EIP when the
> error issues (e0ea32e9). They difference is exactly 45056 bytes 0xb000
> bytes... this number is too precise to be random xD.
>
> What the heck is going on here? Anyone has an idea?
>
> Thanks in advance.
>
> --
> Ole
>
>
> ----- End forwarded message -----
>
> --
> -bill!
> Sent from my computer
> _______________________________________________
> vox-tech mailing list
> vox-tech at lists.lugod.org
> http://lists.lugod.org/mailman/listinfo/vox-tech
--
Brian Lavender
http://www.brie.com/brian/
"There are two ways of constructing a software design. One way is to
make it so simple that there are obviously no deficiencies. And the other
way is to make it so complicated that there are no obvious deficiencies."
Professor C. A. R. Hoare
The 1980 Turing award lecture
More information about the vox-tech
mailing list