OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 11:50 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: [UEFI] Trying to understand "RegisterExceptionCallback"
PostPosted: Fri Apr 05, 2019 11:20 pm 
Offline

Joined: Fri Apr 05, 2019 11:04 pm
Posts: 3
Hello OSdev-people :)

I am new to OS developing and I wanted to go directly with UEFI and x64, trying to avoid BIOS-boot and mode switching. It works good so far, however I can't really get CPU-exception interrupts working. First I tried to do it manually with "lidt" and a lot of inline assembler, but I found the UEFI-function "RegisterExceptionCallback" in the official documentation here:
https://uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf#G21.1036676
This looked promising, so I went with that. However it doesn't really work. Qemu doesn't double/triple fault anymore, when an exception occurs, but my exception handling function isn't called.

This is my code:
Code:
void exceptionDiv() {           // The function I want to be called when the exception occurs
   kprintf("Exception 0x0!\n"); // This never happens
   asm volatile("iretq");
}
// ...
EFI_DEBUG_SUPPORT_PROTOCOL *dsp;
EFI_GUID dspGUID = EFI_DEBUG_SUPPORT_PROTOCOL_GUID;
status = ST->BootServices->LocateProtocol(&dspGUID, NULL, (void**) &dsp);
dsp->RegisterExceptionCallback(dsp, 0, exceptionDiv, EXCEPT_EBC_DIVIDE_ERROR);
kprintf("Test1\n");          // This works
uint32 test1 = 42, test2 = 0;
test1 /= test2;              // The exception occurs here
kprintf("Test2\n");          // This never happens

It seems like there is no more code executed as soon as the exception occurs.


Top
 Profile  
 
 Post subject: Re: [UEFI] Trying to understand "RegisterExceptionCallback"
PostPosted: Sat Apr 06, 2019 12:09 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
You should have just turned the page.
Code:
typedef
VOID (*EFI_EXCEPTION_CALLBACK) (
  IN EFI_EXCEPTION_TYPE        ExceptionType,
  IN OUT EFI_SYSTEM_CONTEXT    SystemContext
  );

So already the type of your callback is wrong. Reading on a bit further:
Quote:
The implementation must handle saving and restoring the processor context to/from the system context record around calls to the registered callback function.

So the "iret" is also wrong and must go, UEFI will handle it for you. That might have been the problem as it would crash so fast you couldn't see the output of the kprintf before it happens. But if that isn't it, are you sure you set the calling conventions correctly?

I find myself repeating the same message, but what does happen? You told us neither the code after the divide error nor the callback is executed, so what does happen instead? QEMU has a monitor window in which you can ask it to print the current RIP, for instance.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: [UEFI] Trying to understand "RegisterExceptionCallback"
PostPosted: Sat Apr 06, 2019 10:52 pm 
Offline

Joined: Fri Apr 05, 2019 11:04 pm
Posts: 3
nullplan wrote:
You told us neither the code after the divide error nor the callback is executed, so what does happen instead?

RIP is exactly 1519 bytes after my exception handler. This is Qemu's output:
Qemu wrote:
check_exception old: 0xffffffff new 0x0
327: v=00 e=0000 i=0 cpl=0 IP=0038:0000000006b469c7 pc=0000000006b469c7 SP=0030:0000000007f0eaa0 env->regs[R_EAX]=000000000000002a
RAX=000000000000002a RBX=0000000007333f98 RCX=0000000006b52004 RDX=0000000000000000
RSI=0000000000000009 RDI=0000000007336018 RBP=0000000007f0eb20 RSP=0000000007f0eaa0
R8 =000000000000023e R9 =000000000000001b R10=0000000007e72080 R11=00000000ffbf826d
R12=0000000007337640 R13=0000000007337648 R14=0000000007f24b60 R15=0000000007336018
RIP=0000000006b469c7 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0

exceptionDiv() is at 0x6b463cf.

I did change my code a little bit, no change though. :(
Code:
VOID EFIAPI exceptionDiv (IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_SYSTEM_CONTEXT SystemContext) {
   printf("Exception!\n");
   while (1==1);
   return;
}

EFI_DEBUG_SUPPORT_PROTOCOL *dsp;
EFI_GUID dspGUID = EFI_DEBUG_SUPPORT_PROTOCOL_GUID;
ST->BootServices->LocateProtocol(&dspGUID, NULL, (void**) &dsp);
dsp->Isa = IsaX64;   // Setting the instruction set to x64
dsp->RegisterExceptionCallback(dsp, 0, NULL, EXCEPT_EBC_DIVIDE_ERROR);         // Unregister old callback
dsp->RegisterExceptionCallback(dsp, 0, exceptionDiv, EXCEPT_EBC_DIVIDE_ERROR);    // Register new callback
dsp->RegisterExceptionCallback(dsp, 0, NULL, EXCEPT_X64_DIVIDE_ERROR);
dsp->RegisterExceptionCallback(dsp, 0, exceptionDiv, EXCEPT_X64_DIVIDE_ERROR);
dsp->RegisterExceptionCallback(dsp, 0, NULL, EXCEPT_IA32_DIVIDE_ERROR);
dsp->RegisterExceptionCallback(dsp, 0, exceptionDiv, EXCEPT_IA32_DIVIDE_ERROR);

RegisterExeptionCallback() returns "EFI_SUCCESS" in all cases.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 72 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group