‘syscall’ Assembly Instruction

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
FunnyGuy9796
Member
Member
Posts: 61
Joined: Tue Sep 13, 2022 9:29 pm
Libera.chat IRC: FunnyGuy9796

‘syscall’ Assembly Instruction

Post 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.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: ‘syscall’ Assembly Instruction

Post 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?
FunnyGuy9796
Member
Member
Posts: 61
Joined: Tue Sep 13, 2022 9:29 pm
Libera.chat IRC: FunnyGuy9796

Re: ‘syscall’ Assembly Instruction

Post 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.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: ‘syscall’ Assembly Instruction

Post by Octocontrabass »

It doesn't make very much sense to use SYSCALL in kernel mode. There are better ways to disable interrupts.
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: ‘syscall’ Assembly Instruction

Post 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.
FunnyGuy9796
Member
Member
Posts: 61
Joined: Tue Sep 13, 2022 9:29 pm
Libera.chat IRC: FunnyGuy9796

Re: ‘syscall’ Assembly Instruction

Post 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?
nullplan
Member
Member
Posts: 1789
Joined: Wed Aug 30, 2017 8:24 am

Re: ‘syscall’ Assembly Instruction

Post 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.
Carpe diem!
FunnyGuy9796
Member
Member
Posts: 61
Joined: Tue Sep 13, 2022 9:29 pm
Libera.chat IRC: FunnyGuy9796

Re: ‘syscall’ Assembly Instruction

Post 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.
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: ‘syscall’ Assembly Instruction

Post 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.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: ‘syscall’ Assembly Instruction

Post 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?
FunnyGuy9796
Member
Member
Posts: 61
Joined: Tue Sep 13, 2022 9:29 pm
Libera.chat IRC: FunnyGuy9796

Re: ‘syscall’ Assembly Instruction

Post 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.
Clover5411
Member
Member
Posts: 25
Joined: Sat Jul 27, 2019 9:41 am

Re: ‘syscall’ Assembly Instruction

Post 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().
Last edited by Clover5411 on Thu Mar 16, 2023 11:53 am, edited 2 times in total.
feryno
Member
Member
Posts: 73
Joined: Thu Feb 09, 2012 6:53 am
Location: Czechoslovakia
Contact:

Re: ‘syscall’ Assembly Instruction

Post 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).
hypervisor-based solutions developer (Intel, AMD)
Post Reply