sysret causes cpu reset
Page 1 of 1

Author:  freax13 [ Mon Jul 15, 2019 1:20 pm ]
Post subject:  sysret causes cpu reset

I'm trying to switch to user-mode (ring 3) on x86_64 with the following code:
mov rcx, 0x80000000
xor r11, r11

I have some virtual memory mapped at 0x80000000 with the flags Flags::PRESENT | Flags::WRITABLE | Flags::USER_ACCESSIBLE. At 0x80000000 I wrote a simple nop instruction (0x90).
I'm expecting the cpu to load rcx (0x80000000) into rip and execute the nop instruction, but the cpu resets before the nop is executed.
I enabled the system call extensions in EFER and wrote the segment selector to STAR.
I have interrupt handlers for almost all cpu exceptions enabled (including double fault), but the cpu resets without causing an exception/calling the handlers when the sysretq instruction is executed.
The qemu log shows the cpu reset:
CPU Reset (CPU 0)
RAX=0000000080000001 RBX=0000000000006882 RCX=0000000080000000 RDX=0000000000000000
RSI=0000000080000001 RDI=000057ac001fffcc RBP=000000000000626a RSP=000057ac001fff38
R8 =fffffffffffffffd R9 =0000000000000802 R10=0000000000000001 R11=0000000000000000
R12=000000000000626a R13=0000000140200000 R14=000000b0071f0000 R15=0000000000006882
RIP=0000000080000000 RFL=00010002 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =001b 0000000000000000 ffffffff 00a0fb00 DPL=3 CS64 [-RA]
SS =0013 0000000000000000 ffffffff 00c0f300 DPL=3 DS   [-WA]
DS =0010 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0000 0000000000000000 0000ffff 00009300 DPL=0 DS   [-WA]
GS =0000 0000000000000000 0000ffff 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0020 000000000024a209 00000067 00008b00 DPL=0 TSS64-busy
GDT=     000000000024a288 0000003f
IDT=     00000000002491f0 00000fff
CR0=80010011 CR2=fffffffffffffff8 CR3=0000000000001000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=0000000000000000 CCO=DYNAMIC
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
XMM08=00000000000000000000000000000000 XMM09=00000000000000000000000000000000
XMM10=00000000000000000000000000000000 XMM11=00000000000000000000000000000000
XMM12=00000000000000000000000000000000 XMM13=00000000000000000000000000000000
XMM14=00000000000000000000000000000000 XMM15=00000000000000000000000000000000

Author:  iansjack [ Mon Jul 15, 2019 1:37 pm ]
Post subject:  Re: sysret causes cpu reset

You should link to a repository containing your complete source code. I'm not sure the snippet that you show is enough for anyone to identify your problem. Have you tested your exception handlers to be sure that they are working? What exactly do they do - the most useful action may be to halt the processor to allow the registers to be inspected.

Author:  freax13 [ Mon Jul 15, 2019 2:04 pm ]
Post subject:  Re: sysret causes cpu reset

I'd prefer not to post the complete source if not absolutley neccessary. I tested the exception handlers and they are working. They are printing the name of the exception and halt the processor

Author:  songziming [ Mon Jul 15, 2019 9:30 pm ]
Post subject:  Re: sysret causes cpu reset

What's the value of STAR and what's the content of your GDT?

For example, this is my configuration:
write_msr(0xc0000081, 0x001b000800000000UL);    // STAR
write_msr(0xc0000082, (u64) syscall_entry);     // LSTAR
gdt[0] = 0UL;                   // dummy
gdt[1] = 0x00a0980000000000UL;  // kernel code
gdt[2] = 0x00c0920000000000UL;  // kernel data
gdt[3] = 0UL;                   // reserved
gdt[4] = 0x00c0f20000000000UL;  // user data
gdt[5] = 0x00a0f80000000000UL;  // user code

You have to leave a gap between kernel and user segments, and the order of code/data is different.

Also, bochs can give you useful information about the exception.

Author:  iansjack [ Mon Jul 15, 2019 11:39 pm ]
Post subject:  Re: sysret causes cpu reset

freax13 wrote:
I'd prefer not to post the complete source if not absolutley neccessary.


I'll leave it for someone with a better crystal ball than mine to make a guess.

Author:  freax13 [ Wed Jul 17, 2019 11:26 am ]
Post subject:  Re: sysret causes cpu reset

I managed to fix it
Turns out I had a number of problems:
1. I didn't load all segment registers
2. The descriptors in my gdt were just plain wrong (thanks songziming for providing examples)
3. The higher levels (2-4) of my pagetable didn't have their entries marked as user-accessible

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group