Date: Mon, 17 Jan 2022 22:31:09 +0000 From: Damian's Proton Mail <damian@dmcyk.xyz> To: Konstantin Belousov <kostikbel@gmail.com> Cc: "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org> Subject: Re: amd64 syscall ABI (vs. Darwin) Message-ID: <94B30813-0034-4F90-9AAC-113402A1A3E8@dmcyk.xyz> In-Reply-To: <YeVxXdPlmYdwV5PI@kib.kiev.ua> References: <Gp_BfNXrv9qjA5V5DpeI-lfdH6EmwKDuqkMLI7DHkses-P6-bT7Ga9p_nURlQC2D4fYuWyf6pFC7s8FPUjWV5Ut7j7uL8iiqx9hv8oePlHs=@dmcyk.xyz> <YeVxXdPlmYdwV5PI@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
> On 17 Jan 2022, at 14:38, Konstantin Belousov <kostikbel@gmail.com> wrote= : > > On Mon, Jan 17, 2022 at 12:41:59PM +0000, Damian Malarczyk wrote: >> Hello, >> >> I'm hacking on a toy project to run Darwin (MachO) binaries on FreeBSD. >> Currently I'm at a stage of syscalls support, and I've noticed a differe= nce in the amd64 ABI that I didn't expect. >> >> FreeBSD is changing values of some registers that aren't used as the sys= call output. e.g., r8-r11 are changed, while r12-r15 don't seem to be affec= ted. >> That's not the case on Darwin, from what I've seen onlyrax, rdx used as = syscall results are changed. >> It looks like FreeBSD's syscalls calling convention is more like standar= d function calling, and r8-r11 should be always caller saved. > It is not 'more like'. FreeBSD follows C ABI for amd64 for syscall > registers handling. An additional twist is that the registers which are > declared as calleee-clobered are zeroed to avoid kernel data leakage to > userspace. Oh I see, this explains it then. >> >> At a first glance Darwin approach seems more optimal, as less registers = get clobbered. Is there any specific reason why this isn't also the case on= FreeBSD? >> I'm also wondering where exactly the register values are changed. When I= look at thetrapframe contents in the sv_set_syscall_retvalsystem vector ca= llback the r8 register value is same as on the input, so it must be changed= somewhere later. Does anyone know where exactly this happens? > > Look at the sys/amd64/amd64/exceptions.S. The fast_syscall entry point > is where we receive control after the syscall instruction. A lot of new things in there for me, but the flow is clear. I was able to f= ind corresponding logic in XNU=E2=80=99s sources too. Earlier I said: > At a first glance Darwin approach seems more optimal But it=E2=80=99s instead the opposite/no difference at all, as in Darwin, t= hey explicitly restore/set all registers, including callee saved r12-r15. Explicitly preserving registers would prevent kernel data leakage too. Doin= g so in FreeBSD would also be an ABI compatible change I think, since users= shouldn=E2=80=99t rely on values in those registers. I=E2=80=99m curious if you see any obvious pros/cons with either approach, = or is it just a more arbitrary implementation choice? Not that I=E2=80=99d propose changing the ABI though, I also want my toy pr= oject to work as a plug-in kernel module. I guess the only other option to emulate Darwin's behaviour would be to int= ercept syscalls in userspace somehow first and manually preserve the regist= er values?
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?94B30813-0034-4F90-9AAC-113402A1A3E8>