From d16b21b17d13ecd88a068bb803df43e53d3b04ba Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Thu, 27 Jun 2024 19:26:11 -0700 Subject: [BOLT][Linux] Support ORC for alternative instructions (#96709) Alternative instruction sequences in the Linux kernel can modify the stack and thus they need their own ORC unwind entries. Since there's only one ORC table, it has to be "shared" among multiple instruction sequences. The kernel achieves this by putting a restriction on instruction boundaries. If ORC state changes at a given IP, only one of the alternative sequences can have an instruction starting/ending at this IP. Then, developers can insert NOPs to guarantee the above requirement is met. The most common use of ORC with alternatives is "pushf; pop %rax" sequence used for paravirtualization. Note that newer kernel versions no longer use .parainstructions; instead, they utilize alternatives for the same purpose. Before we implement a better support for alternatives, we can safely skip ORC entries associated with them. Fixes #87052. --- bolt/test/X86/linux-alt-instruction.s | 49 +++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'bolt/test') diff --git a/bolt/test/X86/linux-alt-instruction.s b/bolt/test/X86/linux-alt-instruction.s index dc1b12a2..fe3abbf 100644 --- a/bolt/test/X86/linux-alt-instruction.s +++ b/bolt/test/X86/linux-alt-instruction.s @@ -38,7 +38,7 @@ # RUN: llvm-bolt %t.exe --print-cfg -o %t.fs4.out | FileCheck %s # CHECK: BOLT-INFO: Linux kernel binary detected -# CHECK: BOLT-INFO: parsed 2 alternative instruction entries +# CHECK: BOLT-INFO: parsed 3 alternative instruction entries .text .globl _start @@ -50,10 +50,12 @@ _start: # CHECK: rdtsc # CHECK-SAME: AltInst: 1 # CHECK-SAME: AltInst2: 2 +# CHECK-SAME: AltInst3: 3 nop # CHECK-NEXT: nop # CHECK-SAME: AltInst: 1 # CHECK-SAME: AltInst2: 2 +# CHECK-SAME: AltInst3: 3 nop nop .L1: @@ -66,6 +68,9 @@ _start: rdtsc .A1: rdtscp +.A2: + pushf + pop %rax .Ae: ## Alternative instruction info. @@ -92,11 +97,51 @@ _start: .word 0x3b # feature flags .endif .byte .L1 - .L0 # org size - .byte .Ae - .A1 # alt size + .byte .A2 - .A1 # alt size .ifdef PADLEN .byte 0 .endif + .long .L0 - . # org instruction + .long .A2 - . # alt instruction +.ifdef FEATURE_SIZE_4 + .long 0x110 # feature flags +.else + .word 0x110 # feature flags +.endif + .byte .L1 - .L0 # org size + .byte .Ae - .A2 # alt size +.ifdef PADLEN + .byte 0 +.endif + +## ORC unwind for "pushf; pop %rax" alternative sequence. + .section .orc_unwind,"a",@progbits + .align 4 + .section .orc_unwind_ip,"a",@progbits + .align 4 + + .section .orc_unwind + .2byte 8 + .2byte 0 + .2byte 0x205 + .section .orc_unwind_ip + .long _start - . + + .section .orc_unwind + .2byte 16 + .2byte 0 + .2byte 0x205 + .section .orc_unwind_ip + .long .L0 + 1 - . + + .section .orc_unwind + .2byte 8 + .2byte 0 + .2byte 0x205 + .section .orc_unwind_ip + .long .L0 + 2 - . + ## Fake Linux Kernel sections. .section __ksymtab,"a",@progbits .section __ksymtab_gpl,"a",@progbits -- cgit v1.1