void sysret()
{
if (EFER.SCE == 0) /* System Call Extension is disable */
do_exception_UD();
if (CR0.PE == 0 || CS.attribute.DPL != 0) /* protected mode is disable or CPL != 0 */
do_exception_GP();
if (CS.attribute.L == 1) /* 64-bit mode */
{
if (REX.W == 1) /* 64-bit operand size */
{
/*
* return to 64-bit code !
*/
CS.selector = STAR.SYSRET_CS + 16; /* 64-bit code segment selector */
CS.selector.RPL = 3; /* CPL = 3 */
CS.attribute.L = 1;
CS.attribute.D = 0;
CS.attribute.P = 1;
CS.attribute.DPL = 3;
CS.base = 0;
CS.limit = 0xFFFFFFFF;
rip = rcx; /* restore rip for return */
} else {
/*
* return to compatibility !
*/
CS.selector = STAR.SYSRET_CS; /* 32-bit code segment selector */
CS.selector.RPL = 3;
CS.attribute.L = 0; /* compatibility mode */
CS.attribute.D = 1; /* 32-bit code */
CS.attribute.P = 1;
CS.attribute.C = 0;
CS.attribute.R = 1;
CS.attribute.DPL = 3;
CS.base = 0;
CS.limit = 0xFFFFFFFF;
rip = (unsigned long long)ecx;
}
SS.selector = START.SYSRET_CS + 8; /* SS selector for return */
rflags = r11; /* restore rflags */
/* goto rip */
} else { /* compatibility or legacy mode */
CS.selector = STAR.SYSRET_CS; /* 32-bit code segment selector */
CS.selector.RPL = 3
CS.attribute.L = 0; /* compatibility mode */
CS.attribute.D = 1; /* 32-bit code */
CS.attribute.P = 1;
CS.attribute.C = 0;
CS.attribute.R = 1;
CS.attribute.DPL = 3;
CS.base = 0;
CS.limit = 0xFFFFFFFF;
SS.selector = STAR.SYSRET_CS + 8;
rflags.IF = 1;
rip = (unsigned long long)ecx;
}
}