Page 1 of 1

‘syscall’ Assembly Instruction

Posted: Sat Feb 25, 2023 8:28 pm
by FunnyGuy9796
As I was reading how to disable interrupts I notice an assembly instruction

Code: Select all

syscall
was used and I was wondering if this would still be applicable in kernel mode rather than user mode. I am aware that disabling interrupts will still be required for functions in user mode but I am curious if this instruction would cause any issues while in kernel mode.

Re: ‘syscall’ Assembly Instruction

Posted: Sat Feb 25, 2023 8:54 pm
by Octocontrabass
FunnyGuy9796 wrote:I was wondering if this would still be applicable in kernel mode rather than user mode.
Did you try looking in the Intel or AMD manuals? This is one of the instructions that Intel and AMD treat differently, so it might be a good idea to check both. SYSCALL and SYSRET are designed to be used as a pair, but SYSRET always returns to user mode, so it doesn't make very much sense to use SYSCALL in kernel mode.
FunnyGuy9796 wrote:I am aware that disabling interrupts will still be required for functions in user mode
Usually you don't want to allow user mode to disable interrupts. Why do you need to do that?

Re: ‘syscall’ Assembly Instruction

Posted: Sat Feb 25, 2023 8:57 pm
by FunnyGuy9796
I am not yet in user mode. I am writing the

Code: Select all

liballoc_lock()
and

Code: Select all

liballoc_unlock
functions for the liballoc memory allocator.

Re: ‘syscall’ Assembly Instruction

Posted: Sat Feb 25, 2023 9:26 pm
by Octocontrabass
It doesn't make very much sense to use SYSCALL in kernel mode. There are better ways to disable interrupts.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 4:54 am
by rdos
FunnyGuy9796 wrote:I am not yet in user mode. I am writing the

Code: Select all

liballoc_lock()
and

Code: Select all

liballoc_unlock
functions for the liballoc memory allocator.
You normally would not implement user mode memory allocation in kernel. It's typically a part of the runtime library of your compiler/linker. You do need some kernel functions to reserve areas for the heap, but the heap itself is not implemented in kernel space.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 6:39 am
by FunnyGuy9796
Oh, ok. I have noticed that most roadmaps that people give examples for have the heap set up after reaching user space. Although, I am wondering, why does the OSDev Wiki roadmap have you setting up memory management before entering user mode?

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 7:22 am
by nullplan
FunnyGuy9796 wrote:Oh, ok. I have noticed that most roadmaps that people give examples for have the heap set up after reaching user space. Although, I am wondering, why does the OSDev Wiki roadmap have you setting up memory management before entering user mode?
You need kernel-side memory management as one of the first things. However, that is a very large term. If you want a traditional higher-half kernel, you will need a physical memory manager, a virtual memory manager (possible two of them, one for kernel-side, one for user-side), a page-table handler to marry the two (you will at some point need to map a known physical address to a known virtual address). And then you will need a memory allocator on top of it all, because you rarely want to spend 4kB of memory on objects that are only a few bytes long. You will also need a page-fault handler to be able to lazily synchronize the TLBs and the page tables.

User-space will also need a way to allocate memory, but will then subdivide the memory it got from the OS further for the objects it allocates, according to its own schemes. So your kernel-mode memory allocator has nothing to do with the user-mode one, and indeed each process can have a different one.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 10:42 am
by FunnyGuy9796
Makes sense. However, when trying to implement liballoc I was reading how to write the lock() function with an example that showed disabling interrupts followed by the ‘syscall’ assembly instruction which led me to believe that it was necessary to be in userspace.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 11:40 am
by rdos
FunnyGuy9796 wrote:Makes sense. However, when trying to implement liballoc I was reading how to write the lock() function with an example that showed disabling interrupts followed by the ‘syscall’ assembly instruction which led me to believe that it was necessary to be in userspace.
Locking is a separate issue. You cannot solve locking issues in user space by disabling interrupts. If you need locks because you support multiple threads, you must implement locks in other ways.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 4:17 pm
by Octocontrabass
FunnyGuy9796 wrote:an example that showed disabling interrupts followed by the ‘syscall’ assembly instruction
That doesn't make sense. Normally, interrupts are only disabled in kernel mode, and the SYSCALL instruction is only used in user mode. Are you sure you weren't looking at two separate examples?

Re: ‘syscall’ Assembly Instruction

Posted: Sun Feb 26, 2023 4:19 pm
by FunnyGuy9796
I was looking for an example in kernel mode. That’s why I was initially wondering why they had included the “syscall” instruction. It had thrown me off because I knew it wasn’t necessary for kernel mode but because I am still learning I just wanted to be sure.

Re: ‘syscall’ Assembly Instruction

Posted: Sun Mar 12, 2023 4:31 am
by Clover5411
I don't know where you found it, but that example seems remarkably wrong. As far as I know, SYSCALL shouldn't be used in kernel mode, and user mode shouldn't be allowed to disable interrupts either. Disabling interrupts isn't the intended purpose of SYSCALL anyway, CLI instruction should be used for that.

There are NMIs, which are interrupts that cannot be disabled by CLI, but I don't fully understand how they work yet, so I can't help you there. Though, I doubt you'll need to disable NMIs for lock().

Re: ‘syscall’ Assembly Instruction

Posted: Wed Mar 15, 2023 1:18 pm
by feryno
FunnyGuy9796:
syscall is designed to be executed from usermode to switch into kernelmode
you can omit its execution in kernemode as users here suggested you already... when you run kernel no need to execute the SYSCALL instruction, you can use the CLI instruction
the only one execution of syscall in kernelmode I've ever seen was in ms windows kernel to detect hypervisors tampering with the address of MSR LSTAR (one of the many patchguard detection methods)

Code: Select all

INITKDBG:00000001402F4470 sub_1402F4470   proc near               ; CODE XREF: .text:000000014018D3DDp
INITKDBG:00000001402F4470                                         ; INITKDBG:00000001402E7923p
INITKDBG:00000001402F4470
INITKDBG:00000001402F4470 var_18          = dword ptr -18h
INITKDBG:00000001402F4470
INITKDBG:00000001402F4470                 mov     ecx, 0C0000084h
INITKDBG:00000001402F4475                 rdmsr
INITKDBG:00000001402F4477                 push    rdx
INITKDBG:00000001402F4478                 push    rax
INITKDBG:00000001402F4479                 and     eax, 0FFFFFEFFh
INITKDBG:00000001402F447E                 wrmsr
INITKDBG:00000001402F4480                 pushfq
INITKDBG:00000001402F4481                 or      [rsp+18h+var_18], 100h
INITKDBG:00000001402F4488                 popfq                 ; enable rflags.TF so when the next instruction execution completes, #DB will be generated
INITKDBG:00000001402F4489                 syscall                 ; #DB generated after this instruction completes, note we are in kernemode but executing syscall instruction
INITKDBG:00000001402F448B                 mov     r10, rcx                 ; grab the real address where MSR LSTAR is pointing
INITKDBG:00000001402F448E                 mov     ecx, 0C0000084h
INITKDBG:00000001402F4493                 pop     rax
INITKDBG:00000001402F4494                 pop     rdx
INITKDBG:00000001402F4495                 wrmsr
INITKDBG:00000001402F4497                 mov     rax, r10
INITKDBG:00000001402F449A                 retn
INITKDBG:00000001402F449A sub_1402F4470   endp
KineticManiac:
you can't trivially disable #NMI on Intel, you can on AMD using the CLGI instruction
I spent a lot of time to solve the #NMI problem on Intel during hypervisor development. Hyper-V uses #NMI to communicate among cpus/cores. I'm developer of hypervisor with nesting capabilities and I had to solve these #NMI delivered into my parent hypervisor (which is solvable trivially by NMI window exiting and #NMI injection using VM-entry interruption-information field in most circumstances, but complicated when #NMI was delivered very late - just before vm entry). Intel has some internal CPU flag to put CPU into blocking mode for further #NMI deliveries, so the CPU handles only one #NMI at any time, the last instruction of such #NMI handler is the IRETQ instruction which unblocks #NMI so further #NMIs could be delivered. It is impossible to check/obtain this internal cpu flag on baremetal, but you can access and modify it when enabling and using VMX (VMCS, guest interruptibility state, blocked by NMI bit). But you can access/modify it only for non-root mode (guest), you still cannot access it for yourself = root mode (your hypervisor).