Skip to content

Commit

Permalink
executor: arm64: declare 'noinline' for SyzOS
Browse files Browse the repository at this point in the history
Apply __attribute__((noinline)) to SyzOS API command handlers to prevent
overly optimizing them.
While at it, rearrange specifiers in guest function declarations
  • Loading branch information
ramosian-glider committed Dec 5, 2024
1 parent 6550493 commit 56c7c51
Showing 1 changed file with 35 additions and 32 deletions.
67 changes: 35 additions & 32 deletions executor/common_kvm_arm64_syzos.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
// Host will map the code in this section into the guest address space.
#define GUEST_CODE __attribute__((section("guest")))

// Prevent function inlining. This attribute is applied to every guest_handle_* function,
// making sure they remain small so that the compiler does not attempt to be too clever
// (e.g. generate switch tables).
#define noinline __attribute__((noinline))

// Start/end of the guest section.
extern char *__start_guest, *__stop_guest;

Expand Down Expand Up @@ -159,7 +164,7 @@ guest_main(uint64 size, uint64 cpu)
guest_uexit((uint64)-1);
}

GUEST_CODE static void guest_execute_code(uint32* insns, uint64 size)
GUEST_CODE static noinline void guest_execute_code(uint32* insns, uint64 size)
{
volatile void (*fn)() = (volatile void (*)())insns;
fn();
Expand All @@ -168,7 +173,7 @@ GUEST_CODE static void guest_execute_code(uint32* insns, uint64 size)
// Perform a userspace exit that can be handled by the host.
// The host returns from ioctl(KVM_RUN) with kvm_run.exit_reason=KVM_EXIT_MMIO,
// and can handle the call depending on the data passed as exit code.
GUEST_CODE static void guest_uexit(uint64 exit_code)
GUEST_CODE static noinline void guest_uexit(uint64 exit_code)
{
volatile uint64* ptr = (volatile uint64*)ARM64_ADDR_UEXIT;
*ptr = exit_code;
Expand Down Expand Up @@ -200,8 +205,7 @@ GUEST_CODE static uint32 get_cpu_id()

// Write value to a system register using an MSR instruction.
// The word "MSR" here has nothing to do with the x86 MSR registers.
__attribute__((noinline))
GUEST_CODE static void
GUEST_CODE static noinline void
guest_handle_msr(uint64 reg, uint64 val)
{
uint32 msr = reg_to_msr(reg);
Expand All @@ -218,7 +222,7 @@ guest_handle_msr(uint64 reg, uint64 val)
}

// See "SMC Calling Convention", https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
GUEST_CODE static void guest_handle_smc(struct api_call_smccc* cmd)
GUEST_CODE static noinline void guest_handle_smc(struct api_call_smccc* cmd)
{
asm volatile(
"mov x0, %[func_id]\n"
Expand All @@ -241,7 +245,7 @@ GUEST_CODE static void guest_handle_smc(struct api_call_smccc* cmd)
"memory");
}

GUEST_CODE static void guest_handle_hvc(struct api_call_smccc* cmd)
GUEST_CODE static noinline void guest_handle_hvc(struct api_call_smccc* cmd)
{
asm volatile(
"mov x0, %[func_id]\n"
Expand Down Expand Up @@ -315,21 +319,21 @@ GUEST_CODE static void guest_handle_hvc(struct api_call_smccc* cmd)
#define ICC_EOIR1_EL1 "S3_0_C12_C12_1"
#define ICC_DIR_EL1 "S3_0_C12_C11_1"

static GUEST_CODE __always_inline void __raw_writel(uint32 val, uint64 addr)
GUEST_CODE static __always_inline void __raw_writel(uint32 val, uint64 addr)
{
asm volatile("str %w0, [%1]"
:
: "rZ"(val), "r"(addr));
}

static GUEST_CODE __always_inline void __raw_writeq(uint64 val, uint64 addr)
GUEST_CODE static __always_inline void __raw_writeq(uint64 val, uint64 addr)
{
asm volatile("str %x0, [%1]"
:
: "rZ"(val), "r"(addr));
}

static GUEST_CODE __always_inline uint32 __raw_readl(uint64 addr)
GUEST_CODE static __always_inline uint32 __raw_readl(uint64 addr)
{
uint32 val;
asm volatile("ldr %w0, [%1]"
Expand All @@ -338,7 +342,7 @@ static GUEST_CODE __always_inline uint32 __raw_readl(uint64 addr)
return val;
}

static GUEST_CODE __always_inline uint64 __raw_readq(uint64 addr)
GUEST_CODE static __always_inline uint64 __raw_readq(uint64 addr)
{
uint64 val;
asm volatile("ldr %x0, [%1]"
Expand All @@ -365,7 +369,7 @@ static GUEST_CODE __always_inline uint64 __raw_readq(uint64 addr)
} while (0)

// Helper to implement guest_udelay().
GUEST_CODE uint64 read_cntvct(void)
GUEST_CODE static uint64 read_cntvct(void)
{
uint64 val;
asm volatile("mrs %0, cntvct_el0"
Expand Down Expand Up @@ -451,7 +455,7 @@ GUEST_CODE static void gicv3_dist_init(int nr_spis)
}

// https://developer.arm.com/documentation/198123/0302/Configuring-the-Arm-GIC
GUEST_CODE void gicv3_enable_redist(uint32 cpu)
GUEST_CODE static void gicv3_enable_redist(uint32 cpu)
{
uint64 redist_base_cpu = gicr_base_cpu(cpu);
uint32 val = readl(redist_base_cpu + GICR_WAKER);
Expand All @@ -462,7 +466,7 @@ GUEST_CODE void gicv3_enable_redist(uint32 cpu)
spin_while_readl(ARM64_ADDR_GICR_BASE + GICR_WAKER, GICR_WAKER_ChildrenAsleep);
}

GUEST_CODE void gicv3_cpu_init(uint32 cpu)
GUEST_CODE static void gicv3_cpu_init(uint32 cpu)
{
uint64 sgi_base = sgi_base_cpu(cpu);

Expand Down Expand Up @@ -522,7 +526,7 @@ GUEST_CODE static void gicv3_irq_enable(uint32 intid)
gicr_wait_for_rwp(cpu);
}

GUEST_CODE static void guest_handle_irq_setup(struct api_call_irq_setup* cmd)
GUEST_CODE static noinline void guest_handle_irq_setup(struct api_call_irq_setup* cmd)
{
int nr_spis = cmd->nr_spis;
if ((nr_spis > VGICV3_MAX_SPI - VGICV3_MIN_SPI) || (nr_spis < 0))
Expand All @@ -545,7 +549,7 @@ GUEST_CODE static void guest_handle_irq_setup(struct api_call_irq_setup* cmd)
: "x1");
}

GUEST_CODE static void guest_handle_memwrite(struct api_call_memwrite* cmd)
GUEST_CODE static noinline void guest_handle_memwrite(struct api_call_memwrite* cmd)
{
uint64 dest = cmd->base_addr + cmd->offset;
switch (cmd->len) {
Expand Down Expand Up @@ -576,7 +580,7 @@ GUEST_CODE static void guest_handle_memwrite(struct api_call_memwrite* cmd)

GUEST_CODE static void guest_prepare_its(int nr_cpus, int nr_devices, int nr_events);

GUEST_CODE static void guest_handle_its_setup(struct api_call_3* cmd)
GUEST_CODE static noinline void guest_handle_its_setup(struct api_call_3* cmd)
{
guest_prepare_its(cmd->args[0], cmd->args[1], cmd->args[2]);
}
Expand Down Expand Up @@ -859,7 +863,7 @@ struct its_cmd_block {

// Guest memcpy implementation is using volatile accesses to prevent the compiler from optimizing it
// into a memcpy() call.
__attribute__((noinline)) GUEST_CODE static void guest_memcpy(void* dst, void* src, size_t size)
GUEST_CODE static noinline void guest_memcpy(void* dst, void* src, size_t size)
{
volatile char* pdst = (char*)dst;
volatile char* psrc = (char*)src;
Expand All @@ -869,7 +873,7 @@ __attribute__((noinline)) GUEST_CODE static void guest_memcpy(void* dst, void* s

// Send an ITS command by copying it to the command queue at the offset defined by GITS_CWRITER.
// https://developer.arm.com/documentation/100336/0106/operation/interrupt-translation-service--its-/its-commands-and-errors.
__attribute__((noinline)) GUEST_CODE static void its_send_cmd(uint64 cmdq_base, struct its_cmd_block* cmd)
GUEST_CODE static noinline void its_send_cmd(uint64 cmdq_base, struct its_cmd_block* cmd)
{
uint64 cwriter = its_read_u64(GITS_CWRITER);
struct its_cmd_block* dst = (struct its_cmd_block*)(cmdq_base + cwriter);
Expand Down Expand Up @@ -954,8 +958,7 @@ GUEST_CODE static void its_init(uint64 coll_tbl,
(~0ULL >> (63 - (h))))

// Avoid inlining this function, because it may cause emitting constants into .rodata.
__attribute__((noinline))
GUEST_CODE static void
GUEST_CODE static noinline void
its_mask_encode(uint64* raw_cmd, uint64 val, int h, int l)
{
uint64 mask = GENMASK_ULL(h, l);
Expand Down Expand Up @@ -1014,15 +1017,15 @@ GUEST_CODE static void its_encode_collection(struct its_cmd_block* cmd, uint16 c
its_mask_encode(&cmd->raw_cmd[2], col, 15, 0);
}

__attribute__((noinline)) GUEST_CODE void guest_memzero(void* ptr, size_t size)
GUEST_CODE static noinline void guest_memzero(void* ptr, size_t size)
{
volatile char* p = (char*)ptr;
for (size_t i = 0; i < size; i++)
p[i] = 0;
}

GUEST_CODE void its_send_mapd_cmd(uint64 cmdq_base, uint32 device_id, uint64 itt_base,
size_t num_idbits, bool valid)
GUEST_CODE static void its_send_mapd_cmd(uint64 cmdq_base, uint32 device_id, uint64 itt_base,
size_t num_idbits, bool valid)
{
struct its_cmd_block cmd;
guest_memzero(&cmd, sizeof(cmd));
Expand All @@ -1035,7 +1038,7 @@ GUEST_CODE void its_send_mapd_cmd(uint64 cmdq_base, uint32 device_id, uint64 itt
its_send_cmd(cmdq_base, &cmd);
}

GUEST_CODE void its_send_mapc_cmd(uint64 cmdq_base, uint32 vcpu_id, uint32 collection_id, bool valid)
GUEST_CODE static void its_send_mapc_cmd(uint64 cmdq_base, uint32 vcpu_id, uint32 collection_id, bool valid)
{
struct its_cmd_block cmd;
guest_memzero(&cmd, sizeof(cmd));
Expand Down Expand Up @@ -1084,7 +1087,7 @@ GUEST_CODE static void its_send_devid_eventid_cmd(uint64 cmdq_base, uint8 cmd_nr
its_send_cmd(cmdq_base, &cmd);
}

GUEST_CODE void its_send_movall_cmd(uint64 cmdq_base, uint32 vcpu_id, uint32 vcpu_id2)
GUEST_CODE static void its_send_movall_cmd(uint64 cmdq_base, uint32 vcpu_id, uint32 vcpu_id2)
{
struct its_cmd_block cmd;
guest_memzero(&cmd, sizeof(cmd));
Expand Down Expand Up @@ -1118,7 +1121,7 @@ GUEST_CODE static void its_send_sync_cmd(uint64 cmdq_base, uint32 vcpu_id)
its_send_cmd(cmdq_base, &cmd);
}

GUEST_CODE static void guest_handle_its_send_cmd(struct api_call_its_send_cmd* cmd)
GUEST_CODE static noinline void guest_handle_its_send_cmd(struct api_call_its_send_cmd* cmd)
{
switch (cmd->type) {
case GITS_CMD_MAPD: {
Expand Down Expand Up @@ -1165,11 +1168,11 @@ GUEST_CODE static void guest_handle_its_send_cmd(struct api_call_its_send_cmd* c
}
}

__attribute__((noinline)) GUEST_CODE static void guest_setup_its_mappings(uint64 cmdq_base,
uint64 itt_tables,
uint32 nr_events,
uint32 nr_devices,
uint32 nr_cpus)
GUEST_CODE static noinline void guest_setup_its_mappings(uint64 cmdq_base,
uint64 itt_tables,
uint32 nr_events,
uint32 nr_devices,
uint32 nr_cpus)
{
if ((nr_events < 1) || (nr_devices < 1) || (nr_cpus < 1))
return;
Expand Down Expand Up @@ -1230,7 +1233,7 @@ void gic_rdist_enable_lpis(uint64 cfg_table, size_t cfg_table_size,
//   452158:       3d800000        str     q0, [x0]
//   45215c:       d65f03c0        ret
// , which for some reason hangs.
__attribute__((noinline)) GUEST_CODE static void configure_lpis(uint64 prop_table, int nr_devices, int nr_events)
GUEST_CODE static noinline void configure_lpis(uint64 prop_table, int nr_devices, int nr_events)
{
int nr_lpis = nr_devices * nr_events;
volatile uint8* tbl = (uint8*)prop_table;
Expand Down

0 comments on commit 56c7c51

Please sign in to comment.