Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCC 12.1.0 x86-64 build is broken #331

Open
heatd opened this issue Jul 1, 2022 · 2 comments
Open

GCC 12.1.0 x86-64 build is broken #331

heatd opened this issue Jul 1, 2022 · 2 comments

Comments

@heatd
Copy link
Contributor

heatd commented Jul 1, 2022

GCC generates SSE instructions in thread_init_early(), which makes the kernel die at runtime with "unhandled invalid op, halting".

@travisg
Copy link
Member

travisg commented Jul 1, 2022

Yeah, that's a tough problem. I've known about it for a while and it only really shows up on x86-64 AFAIK.

The problem is there is code in LK that wants to use floating point (some apps, fpu test code, etc) and code that should not (kernel, drivers, interrupt controllers, etc). The latter shouldn't use it because it can be invoked from an interrupt handler and since the interrupt handler code doesn't save fpu state, at worst it'll corrupt whatever the kernel application state is.

Usually kernels avoid this problem by simply forbidding x87/SSE/AVX entirely in the kernel, but since LK is a mixed environment where the kernel and applications to the kernel are compiled together you end up without a clear line.

What LK has done on most arches is simply avoid using floating point code in any core kernel bits and then assume the compiler wont use the instructions. Alas, x86 and especially newer GCC and clang compilers, love to use SSE at the drop of a hat to do things like bulk zero fill stuff (what thread_init_early() is probably doing). What I'd love to see is a switch that simply disables this behavior: only use FPU for FPU stuff, and then the status quo would be met. Otherwise I only see two solutions:

a) define some way in the build system to mark modules as 'may use fpu' and 'no fpu' and then segregate modules accordingly. Would work well except for shared bits like libc (printf for example). Dunno what to do about it.
b) find a switch to disable this feature on the compiler.
c) add full fpu save to the interrupt/exception glue on x86 and then just let the compiler use it however it wants.

C is probably the easieest to do, though x86 has multiple mechanisms to save fpu state so will need to do some thinking about that. Not as ideal performance wise, but really x86 is not LK's main platform, so getting it to work is better than getting it to work optimally.

@travisg
Copy link
Member

travisg commented Aug 16, 2022

I think I've mostly solved this problem in the interim by taking the B route, though I think there are a few places that may still trigger the problem. Now, on x86, by default code is compiled without any fpu support and various modules have to opt in at the module or file level to add it.

The problematic parts are shared modules like libc, which may want both fpu and non fpu case. Printf is a good example of this. For the moment printf is simply compiled without fpu and so %f stopped working in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants