https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120008
Bug ID: 120008 Summary: RFE: x86: explicit compiler support for SMAP stac/clac (possibly via __attribute__((user))) or similar Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: hpa at zytor dot com Target Milestone: --- When doing user space memory references from kernel space, x86 needs to use the stac and clac instructions to protect those memory references. Currently, as far as I can tell, there is no support for stac and clac in gcc, which means the kernel needs to perform them using explicit assembly statements. This has several problems: 1. stac/clac, though fairly expensive on existing hardware (estimated 3% of all kernel time is stac/clac), cannot be CSE'd by the compiler. 2. The compiler not being aware of them means that it cannot move kernel memory references out of the stac/clac region. 3. The stac/clac asm statements end up having to use a memory clobber or be marked volatile together which each user space reference. This greatly limits the flexibility of gcc to optimize around these; furthermore, it makes it far likely that kernel memory references will remain in the stac/clac region. The kernel will likely need to continue to use assembly wrappers for the actual user space reference due to the need for exception fixups, but it would be a great improvement to have the compiler understand stac and clac, and optionally the ((user)) attribute which is already used to decorate such pointers in the kernel via the __user macro (which definition is used depends on the compiler used [or sparse]): [include/linux/compiler_types.h] #define __user __attribute__((noderef, address_space(__user))) #define __user __attribute__((user)) #define __user BTF_TYPE_TAG(user) ... where BTF_TYPE_TAG() is defined as: /* * Skipped when running bindgen due to a libclang issue; * see https://github.com/rust-lang/rust-bindgen/issues/2244. */ #if defined(CONFIG_DEBUG_INFO_BTF) && defined(CONFIG_PAHOLE_HAS_BTF_TAG) && \ __has_attribute(btf_type_tag) && !defined(__BINDGEN__) # define BTF_TYPE_TAG(value) __attribute__((btf_type_tag(#value))) #else # define BTF_TYPE_TAG(value) /* nothing */ #endif A user attribute, and letting the compiler generate stac/clac if enabled via compiler options would be a rather neat solution. Although the kernel needs to patch out stac and clac at runtime if not supported on the CPU in question, these instructions could be located by the objtool postprocessor that the kernel uses. That being said, we also have a try ... catch ... like mechanism in the kernel for when a large number of user space references need to be performed in sequence. It MAY be necessary to add some compiler understanding of those constructs; if nothing else it would be nice to be able to not have to add memory clobbers as those affects kernel memory, too. Perhaps the simplest solution to *that* is to declare __user to be something like "volatile __attribute__((user))"; user space really is volatile as far as the kernel is concerned (since other threads can be running in the same address space at the same time.)