为什么 Linux 内核复制实现使用 AC 标志?

Why does the Linux Kernel copy implementation use the AC flag?

Linux 内核复制例程中 copy_user_enhanced_fast_string 的实现在结语和序言中使用了 stac/clacperf annotate 显示以下代码:

stac 
cmp  [=11=]x40,%edx
jb   0xffffffff91281f5c
mov  %edx,%ecx
rep  movsb %ds:(%rsi),%es:(%rdi)
xor  %eax,%eax
clac
retq              

AC 是 "Alignment check (or access control) flag".

例程中使用stac/clac是什么原因?如果我们简单地删除它们会有什么后果?

通常在管理员模式下所有页面访问检查都被禁用,内核可以读取或写入任何页面,无论它是只读的还是标记为管理员或用户页面。但是,如果启用 Supervisor-Mode Access Protection (CR4.SMAP = 1),则 AC 标志控制内核是否可以读取或写入用户模式页面。如果 EFLAGS.AC 为 0,则读取或写入用户模式页面将导致页面错误异常。如果 EFLAGS.AC 为 1,则允许内核读取和写入用户模式页面。

发明了 STAC 和 CLAC 指令,以允许快速轻松地更改代码中的 AC 标志,就像您的示例中那样。通过设置 EFLAGS.AC 允许 REP MOVSB 指令访问用户模式页面。通过在最后清除 EFLAGS.AC,内核再次受到保护,免受可能被恶意代码利用的意外用户模式访问。