Return from interrupt without iret (2024)

Post Reply

  • Print view

10 posts• Page 1 of 1

YDeeps1
Member
Return from interrupt without iret (1)
Posts: 69
Joined: Tue Aug 31, 2021 7:25 am
Discord: speedy.dev
Contact:

Contact YDeeps1

Return from interrupt without iret

  • Quote

Postby YDeeps1 »

Say a software interrupt just happened. How would you "acknowledge" the interrupt without using an IRET instruction? I tried simply clearing the interrupt data from the stack and then setting the interrupt flag but that does not work very well. The wiki also does not make it clear what steps are required in order to exit the interrupt state.

Thanks!

Top

nexos
Member
Return from interrupt without iret (2)
Posts: 1072
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Return from interrupt without iret

  • Quote

Postby nexos »

Interrupts always return with IRET. Very rarely is there an exception to that rule. If you want to just acknowledge, then send EOI in the case of a hardware interrupt, and then use IRET

"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg

Top

iansjack
Member
Return from interrupt without iret (4)
Posts: 4604
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Return from interrupt without iret

  • Quote

Postby iansjack »

How would a software interrupt "just happen"? Either you executed an "int" instruction or you didn't. And why are you reluctant to use an "iret" instruction to end the interrupt handler?

Top

Korona
Member
Return from interrupt without iret (5)
Posts: 999
Joined: Thu May 17, 2007 1:27 pm
Contact:

Contact Korona

Re: Return from interrupt without iret

  • Quote

Postby Korona »

It's not really possible to return from an interrupt without iret unless you're willing to add strange hacks. You need an atomic way to jump to a user mode address and to set IF to zero at the same time¹. Outside iret, you could use something like sysret for that purpose, but it is more messy and not intended for the purpose of returning from an arbitrary interrupt.

¹ Technically, that's not required but any other design can easily run into nasty pitfalls.

managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].

Top

Ringding
Posts: 8
Joined: Fri Nov 26, 2021 11:08 am

Re: Return from interrupt without iret

  • Quote

Postby Ringding »

Upon entry the interrupt flag gets cleared. The iret instruction restores it because it pops the previous flags from the stack.

iret is basically: popf + retf, just that the ordering on the stack is reversed. In order to actually replace it with these two instructions, you would need to do quite some stack shuffling. But I cannot think of a good reason to do so.

Top

Octocontrabass
Member
Return from interrupt without iret (6)
Posts: 5239
Joined: Mon Mar 25, 2013 7:01 pm

Re: Return from interrupt without iret

  • Quote

Postby Octocontrabass »

YDeeps1 wrote:without using an IRET instruction

Why don't you want to use an IRET instruction?

Top

feryno
Member
Return from interrupt without iret (7)
Posts: 68
Joined: Thu Feb 09, 2012 6:53 am
Location: Czechoslovakia
Contact:

Contact feryno

Re: Return from interrupt without iret

  • Quote

Postby feryno »

I had to exit interrupt handler without iretq too. But that was very special case. There is no way to block #NMI in Intel VMX root mode unlike at AMD SVM where you can (using CLGI instruction). While my hypervisor accepted #NMI I wanted to let the CPU in #NMI blocking mode to prevent more #NMI to arrive as I was able to inject only 1 #NMI into guest during every VM entry. These #NMI came as IPIs from different cpus/cores where hyper-v was running as a child under nested environment. At the end I solved my problem but during observation and development I had to try that way to leave #NMI blocked so I had to avoid iretq as iretq unblocks #NMI.
I used this way at the end of my #NMI handler:

Code: Select all

push rax; now the stack looks this way:; qword [rsp+8*0] RAX; qword [rsp+8*1] RIP; word [rsp+8*2] CS; qword [rsp+8*3] RFLAGS; qword [rsp+8*4] RSP; word [rsp+8*5] SS; this leaves interrupt handler and lets NMIs blocked:mov rax,rsplss rsp,[rax+8*4]; load RSP from qword [rax+8*4] and SS from [rax+8*4+8]push qword [rax+8*3]popfpush qword [rax+8*2]; CSpush qword [rax+8*1]; RIPmov rax,[rax+8*0]; restore RAXretf

hypervisor-based solutions developer (Intel, AMD)

Top

nullplan
Member
Return from interrupt without iret (8)
Posts: 1651
Joined: Wed Aug 30, 2017 8:24 am

Re: Return from interrupt without iret

  • Quote

Postby nullplan »

This solution has the drawback of executing kernel code on user stack. After the lss instruction, any exception that occurs will be taken on user stack. After the popf, any external interrupt will be as well. User space can make you hit unmapped space, leading to double-fault. Alternatively, second user-space thread can manipulate the stack frame, leading to ring 0 arbitrary code execution. Attacker only has to get lucky once, and can try as often as they want.

Carpe diem!

Top

rdos
Member
Return from interrupt without iret (9)
Posts: 3198
Joined: Wed Oct 01, 2008 1:55 pm

Re: Return from interrupt without iret

  • Quote

Postby rdos »

First, I feel it is a bad idea to let software interrupts from the application disable interrupts. You should use the IDT entry that keeps interrupts enabled.

When it comes to not using iret, it's possible to use retf instead, provided you don't care about restoring the state of flags (which assumes you either enabled interrupts specifically, or used a interrupt gate that doesn't disable interrupts.

However, I think it would be more useful to modify the contents of the flag image on the stack instead if you want to return specific flags (like NC/CY) to the caller.

Another issue is if the kernel even allow software interrupts from user space. This is decided per IDT entry. In my kernel, all IDTs disallow software interrupts from the application, and they are instead emulated in the GPF handler.

Also, iret doesn't acknowledge an interrupt. It's just a way to unwind the call stack. It's EOI that acknowledge a hardware interrupt, and if you forget that and just use iret then hardware interrupts will be messed up. For software interrupts, there is no acknowledge.

Top

feryno
Member
Return from interrupt without iret (10)
Posts: 68
Joined: Thu Feb 09, 2012 6:53 am
Location: Czechoslovakia
Contact:

Contact feryno

Re: Return from interrupt without iret

  • Quote

Postby feryno »

nullplan - exactly as you wrote, this method is useless for OS development.
The #NMI arrived in vmx root mode so before #NMI hypervisor stack was loaded (ring-1, VCMS.host_RSP, VMCS.host_SS etc) and when transferring to #NMI handler the private NMI stack was loaded using hypervisor VMCS.host_TSS.IST feature. So at the end of NMI handler the LSS loaded original hypervisor stack, not guest kernelmode stack (ring0) either guest usermode stack (ring3).
These #NMI always arrived as IPI from different cpus/cores and were send by hyper-v, I had to prevent delivering more than 1 #NMI during 1 cycle of vmx root mode (from vm exit till vm entry). During vm entry I had to inject this captured #NMI back into guest, I did not care whether the guest was going to be in ring0 or ring3, handling that was let for cpu (hardware). But the origin of these #NMI was certainly from hyper-v because disabling hyper-v in registry and rebooting then no more #NMI captured in my hypervisor. Hyper-v was running in ring0 mode, not in ring-1. My hypervisor was running in ring-1 as a parent and provided nested capabilities for child hyper-v (so hyper-v was thinking it was running in ring-1 but in fact it was running in ring0 and my parent hypervisor provided emulation of ring-1 instructions for hyper-v).
It was a nightmare but finally I solved that. I just had to keep ring-1 execution with #NMI blocked after capturing #NMI (avoid IRETQ at the end of #NMI handler) so no more than 1 #NMI arrived, then during vm entry I had to clear NMI blocking for guest in VMCS and inject the NMI into guest using VMCS fields so the #NMI was delivered to guest immediately at vm entry. It was very specific situation. For OS development I do not see any advantage of avoiding IRETQ. From hypervisor point you can easily manipulate guest state whether you want your guest is in NMI blocking mode or unblocked mode using 1 bit in VMCS but for root mode there is no such way how to change NMI blocking. My only one idea was to avoid IRETQ which let cpu in NMI blocking mode.
On AMD there is no such problem as at AMD SVM you can easily toggle NMI blocking so #NMI never arrives into your hypervisor. The problem was only at Intel VMX where you can't (at Intel you can only unblock NMI blocking by execution of IRETQ but there is no way how to set CPU into NMI blocking mode).

hypervisor-based solutions developer (Intel, AMD)

Top

Post Reply

  • Print view

10 posts• Page 1 of 1

Return to “OS Development”

Jump to

  • Operating System Development
  • ↳ OS Development
  • Everything Else
  • ↳ General Programming
  • ↳ General Ramblings
  • ↳ Auto-Delete Forum
  • OSDev.org
  • ↳ OSDev Wiki
  • ↳ About this site
Return from interrupt without iret (2024)

References

Top Articles
Latest Posts
Recommended Articles
Article information

Author: Terence Hammes MD

Last Updated:

Views: 5614

Rating: 4.9 / 5 (49 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.