I got to the point with my hobby of the x86_64 UEFI kernel, where the user code calls the system code, but it generates a general security error with error code 0 at 0x1B: 0x0 (0x1B is the user mode code segment selector). In a single step, I realized that SYSRET does not return to the address contained in RCX, but instead of zero. I am debugging qemu-system-x86_64 with and without KVM. Attached two screenshots to this phenomenon. Can someone explain this and tell me what I'm doing wrong?
MSR 0xC0000080 = 0x0000000000000501 MSR 0xC0000081 = 0x001B00083D906D79 MSR 0xC0000082 = 0x000000003D906D79 MSR 0xC0000083 = 0x000000003D906D79 MSR 0xC0000084 = 0x0000000000000300
Interrupts are disabled using the cli and Local APIC entries.


GDT:
{ 0, 0, 0, 0x9A, 0x20, 0 }; // 0x08 ring 0 code { 0, 0, 0, 0x92, 0x00, 0 }; // 0x10 ring 0 data { 0, 0, 0, 0xFA, 0x20, 0 }; // 0x1B ring 3 code { 0, 0, 0, 0xF2, 0x00, 0 }; // 0x23 ring 3 data { 0, 0, 0, 0xFA, 0x20, 0 }; // 0x2B ring 3 code { 0, 0, 0, 0xF2, 0x00, 0 }; // 0x33 ring 3 data typedef struct PACKED ENTRY { U16 limit_0_15; U16 base_0_15; U8 base_16_23; U8 access; U8 granularity; U8 base_24_31; } ENTRY, *PENTRY;
EDIT: After reading the instructions again, I noticed that CS (STAR.SYSRET_CS + 16) returns in long mode | 3, so I duplicated user-mode segment descriptors to be sure, but the results are the same.