0

I am a bit confused about the use of syscalls in OSs, assembly, and machine code.

From what I have understood, syscalls are the interface for users and applications to request services and resources from the OS, and their implementation depends on the type of OS used in the machine. Their implementation is made in machine code.

So, why is there "syscall" instruction in the x86-64 ISA, if those are only OS-relevant?

Is it true, and if so what happens in the unpractical scenario where there is no OS on the machine? Is the "syscall" machine instruction unusable?

I have looked it up, and from what I have found most ISAs "guess" the use of OS in the computer, and by default provide fast and easy way to invoke those through machine code that directs the execution to a place in the kernel code that includes the implementatoin of the syscalls.

  • 2
    I would love to see the source that says there is guessing involved. – Scott Hunter Aug 16 '23 at 12:02
  • 2
    You can think of `syscall` as a `call` that goes to a fixed address with elevated privileges. It's a way to transfer control to an OS. If you don't have a subroutine and you just `call` into the void, that will also not work. Similarly if you don't have an OS, `syscall` will not work. Note that the OS itself sets up the address that `syscall` will use. – Jester Aug 16 '23 at 12:13
  • 1
    Many processors offer instructions and/or features that are not used by every program or application. If there's no handler for syscall, then using that instruction makes no sense and simply would not be done in that environment. There's no requirement that a program uses every possible feature of the processor. – Erik Eidt Aug 16 '23 at 12:20
  • @ScottHunter there is no source saying that but it seems like the x86-64 ISA supports syscalls for OS without knowing if there is an actual OS on the machine – Idan Rosenzweig Aug 16 '23 at 12:33
  • 3
    Instructions are added because they are deemed useful. Most systems will use an OS, and hence a fast way to invoke system calls is useful. The software interrupt instruction `INT` has always been there and was the classic way to invoke the OS. `syscall` and `sysenter` have been added as a faster version. `syscall` has to be enabled by the OS, if you have no OS it's not enabled and trying to use it will result in a #UD exception. There are many instructions that are unusable without an OS (which for the cpu means protected or long mode code running at privilege level 0). – Jester Aug 16 '23 at 13:08
  • 1
    Maybe the writeup at https://stackoverflow.com/questions/56854297/how-syscall-knows-where-to-jump would help you. – teapot418 Aug 16 '23 at 13:49
  • *and by default provide fast and easy way to invoke those through machine code that directs the execution to a place in the kernel code that includes the implementatoin [sic] of the syscalls.* - Yes, that's exactly what AMD64 `syscall` is. As Jester points out, the OS has to enable it by setting a bit in an MSR (IA32_EFER.SCE - https://en.wikipedia.org/wiki/Control_register#Additional_Control_registers_in_Intel_x86-64_series) otherwise `syscall` will #UD fault as an illegal instruction. – Peter Cordes Aug 16 '23 at 15:25
  • "there is no source saying that but it seems like the x86-64 ISA supports syscalls for OS without knowing if there is an actual OS on the machine" — this is the right idea — but what is remarkable or surprising about that to you? – Erik Eidt Aug 16 '23 at 19:19

1 Answers1

4

Because some OS features require a special hardware support. Without that support such OSes cannot run. So, CPU designers have to either provide those features – or know, that most modern OSes will never run on their system. Some low power CPUs do take that route.

Most modern OSes use "sandboxing" of user programs – they put each program into its own "sandbox", isolate it from other programs and from the real hardware. This protects the stability - a crash of one program will be contained, and will not cascade into a crash of other programs, or the entire system. It allows to run programs with different permissions on the same computer. It even allows to safely run programs that are somewhat malicious.

Those sandboxing features are almost infeasible without CPU support. The OS can never safely let the CPU to execute the code, knowing well that it will gladly send a "format all" command to the drive, if only some code from the Internet would tell it so. The only option left is to emulate the code in software. Software emulation is very slow, and there is something silly in the notion that we need a x86_64 emulator to safely run programs on a x86_64 CPU, don't you think?

So the CPU designers provide the features, that OSes need:

  • virtual memory, so OS can provide a fake memory map to the programs, and limit their access to real memory and memory-mapped IO devices. This adds the related instructions: "enable/disable virtual memory", "modify virtual map".
  • user ("sandbox") and kernel ("system") modes, so the program cannot run some instructions that can break it free from the sandbox (for example – the one that would disable virtual memory). This warrants "enter sandbox" and "leave sandbox" instructions.

The syscall is a "leave sandbox" instruction. It is necessary to run modern "sandboxing" OSes. There are some other ways to do a "leave sandbox" action (x86_64 itself has an older int instruction), but syscall was designed to do it faster.