cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bench_trigger.c (7861B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Facebook */
      3#include "bench.h"
      4#include "trigger_bench.skel.h"
      5#include "trace_helpers.h"
      6
      7/* BPF triggering benchmarks */
      8static struct trigger_ctx {
      9	struct trigger_bench *skel;
     10} ctx;
     11
     12static struct counter base_hits;
     13
     14static void trigger_validate(void)
     15{
     16	if (env.consumer_cnt != 1) {
     17		fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
     18		exit(1);
     19	}
     20}
     21
     22static void *trigger_base_producer(void *input)
     23{
     24	while (true) {
     25		(void)syscall(__NR_getpgid);
     26		atomic_inc(&base_hits.value);
     27	}
     28	return NULL;
     29}
     30
     31static void trigger_base_measure(struct bench_res *res)
     32{
     33	res->hits = atomic_swap(&base_hits.value, 0);
     34}
     35
     36static void *trigger_producer(void *input)
     37{
     38	while (true)
     39		(void)syscall(__NR_getpgid);
     40	return NULL;
     41}
     42
     43static void trigger_measure(struct bench_res *res)
     44{
     45	res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
     46}
     47
     48static void setup_ctx(void)
     49{
     50	setup_libbpf();
     51
     52	ctx.skel = trigger_bench__open_and_load();
     53	if (!ctx.skel) {
     54		fprintf(stderr, "failed to open skeleton\n");
     55		exit(1);
     56	}
     57}
     58
     59static void attach_bpf(struct bpf_program *prog)
     60{
     61	struct bpf_link *link;
     62
     63	link = bpf_program__attach(prog);
     64	if (!link) {
     65		fprintf(stderr, "failed to attach program!\n");
     66		exit(1);
     67	}
     68}
     69
     70static void trigger_tp_setup(void)
     71{
     72	setup_ctx();
     73	attach_bpf(ctx.skel->progs.bench_trigger_tp);
     74}
     75
     76static void trigger_rawtp_setup(void)
     77{
     78	setup_ctx();
     79	attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);
     80}
     81
     82static void trigger_kprobe_setup(void)
     83{
     84	setup_ctx();
     85	attach_bpf(ctx.skel->progs.bench_trigger_kprobe);
     86}
     87
     88static void trigger_fentry_setup(void)
     89{
     90	setup_ctx();
     91	attach_bpf(ctx.skel->progs.bench_trigger_fentry);
     92}
     93
     94static void trigger_fentry_sleep_setup(void)
     95{
     96	setup_ctx();
     97	attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);
     98}
     99
    100static void trigger_fmodret_setup(void)
    101{
    102	setup_ctx();
    103	attach_bpf(ctx.skel->progs.bench_trigger_fmodret);
    104}
    105
    106static void *trigger_consumer(void *input)
    107{
    108	return NULL;
    109}
    110
    111/* make sure call is not inlined and not avoided by compiler, so __weak and
    112 * inline asm volatile in the body of the function
    113 *
    114 * There is a performance difference between uprobing at nop location vs other
    115 * instructions. So use two different targets, one of which starts with nop
    116 * and another doesn't.
    117 *
    118 * GCC doesn't generate stack setup preample for these functions due to them
    119 * having no input arguments and doing nothing in the body.
    120 */
    121__weak void uprobe_target_with_nop(void)
    122{
    123	asm volatile ("nop");
    124}
    125
    126__weak void uprobe_target_without_nop(void)
    127{
    128	asm volatile ("");
    129}
    130
    131static void *uprobe_base_producer(void *input)
    132{
    133	while (true) {
    134		uprobe_target_with_nop();
    135		atomic_inc(&base_hits.value);
    136	}
    137	return NULL;
    138}
    139
    140static void *uprobe_producer_with_nop(void *input)
    141{
    142	while (true)
    143		uprobe_target_with_nop();
    144	return NULL;
    145}
    146
    147static void *uprobe_producer_without_nop(void *input)
    148{
    149	while (true)
    150		uprobe_target_without_nop();
    151	return NULL;
    152}
    153
    154static void usetup(bool use_retprobe, bool use_nop)
    155{
    156	size_t uprobe_offset;
    157	struct bpf_link *link;
    158
    159	setup_libbpf();
    160
    161	ctx.skel = trigger_bench__open_and_load();
    162	if (!ctx.skel) {
    163		fprintf(stderr, "failed to open skeleton\n");
    164		exit(1);
    165	}
    166
    167	if (use_nop)
    168		uprobe_offset = get_uprobe_offset(&uprobe_target_with_nop);
    169	else
    170		uprobe_offset = get_uprobe_offset(&uprobe_target_without_nop);
    171
    172	link = bpf_program__attach_uprobe(ctx.skel->progs.bench_trigger_uprobe,
    173					  use_retprobe,
    174					  -1 /* all PIDs */,
    175					  "/proc/self/exe",
    176					  uprobe_offset);
    177	if (!link) {
    178		fprintf(stderr, "failed to attach uprobe!\n");
    179		exit(1);
    180	}
    181	ctx.skel->links.bench_trigger_uprobe = link;
    182}
    183
    184static void uprobe_setup_with_nop(void)
    185{
    186	usetup(false, true);
    187}
    188
    189static void uretprobe_setup_with_nop(void)
    190{
    191	usetup(true, true);
    192}
    193
    194static void uprobe_setup_without_nop(void)
    195{
    196	usetup(false, false);
    197}
    198
    199static void uretprobe_setup_without_nop(void)
    200{
    201	usetup(true, false);
    202}
    203
    204const struct bench bench_trig_base = {
    205	.name = "trig-base",
    206	.validate = trigger_validate,
    207	.producer_thread = trigger_base_producer,
    208	.consumer_thread = trigger_consumer,
    209	.measure = trigger_base_measure,
    210	.report_progress = hits_drops_report_progress,
    211	.report_final = hits_drops_report_final,
    212};
    213
    214const struct bench bench_trig_tp = {
    215	.name = "trig-tp",
    216	.validate = trigger_validate,
    217	.setup = trigger_tp_setup,
    218	.producer_thread = trigger_producer,
    219	.consumer_thread = trigger_consumer,
    220	.measure = trigger_measure,
    221	.report_progress = hits_drops_report_progress,
    222	.report_final = hits_drops_report_final,
    223};
    224
    225const struct bench bench_trig_rawtp = {
    226	.name = "trig-rawtp",
    227	.validate = trigger_validate,
    228	.setup = trigger_rawtp_setup,
    229	.producer_thread = trigger_producer,
    230	.consumer_thread = trigger_consumer,
    231	.measure = trigger_measure,
    232	.report_progress = hits_drops_report_progress,
    233	.report_final = hits_drops_report_final,
    234};
    235
    236const struct bench bench_trig_kprobe = {
    237	.name = "trig-kprobe",
    238	.validate = trigger_validate,
    239	.setup = trigger_kprobe_setup,
    240	.producer_thread = trigger_producer,
    241	.consumer_thread = trigger_consumer,
    242	.measure = trigger_measure,
    243	.report_progress = hits_drops_report_progress,
    244	.report_final = hits_drops_report_final,
    245};
    246
    247const struct bench bench_trig_fentry = {
    248	.name = "trig-fentry",
    249	.validate = trigger_validate,
    250	.setup = trigger_fentry_setup,
    251	.producer_thread = trigger_producer,
    252	.consumer_thread = trigger_consumer,
    253	.measure = trigger_measure,
    254	.report_progress = hits_drops_report_progress,
    255	.report_final = hits_drops_report_final,
    256};
    257
    258const struct bench bench_trig_fentry_sleep = {
    259	.name = "trig-fentry-sleep",
    260	.validate = trigger_validate,
    261	.setup = trigger_fentry_sleep_setup,
    262	.producer_thread = trigger_producer,
    263	.consumer_thread = trigger_consumer,
    264	.measure = trigger_measure,
    265	.report_progress = hits_drops_report_progress,
    266	.report_final = hits_drops_report_final,
    267};
    268
    269const struct bench bench_trig_fmodret = {
    270	.name = "trig-fmodret",
    271	.validate = trigger_validate,
    272	.setup = trigger_fmodret_setup,
    273	.producer_thread = trigger_producer,
    274	.consumer_thread = trigger_consumer,
    275	.measure = trigger_measure,
    276	.report_progress = hits_drops_report_progress,
    277	.report_final = hits_drops_report_final,
    278};
    279
    280const struct bench bench_trig_uprobe_base = {
    281	.name = "trig-uprobe-base",
    282	.setup = NULL, /* no uprobe/uretprobe is attached */
    283	.producer_thread = uprobe_base_producer,
    284	.consumer_thread = trigger_consumer,
    285	.measure = trigger_base_measure,
    286	.report_progress = hits_drops_report_progress,
    287	.report_final = hits_drops_report_final,
    288};
    289
    290const struct bench bench_trig_uprobe_with_nop = {
    291	.name = "trig-uprobe-with-nop",
    292	.setup = uprobe_setup_with_nop,
    293	.producer_thread = uprobe_producer_with_nop,
    294	.consumer_thread = trigger_consumer,
    295	.measure = trigger_measure,
    296	.report_progress = hits_drops_report_progress,
    297	.report_final = hits_drops_report_final,
    298};
    299
    300const struct bench bench_trig_uretprobe_with_nop = {
    301	.name = "trig-uretprobe-with-nop",
    302	.setup = uretprobe_setup_with_nop,
    303	.producer_thread = uprobe_producer_with_nop,
    304	.consumer_thread = trigger_consumer,
    305	.measure = trigger_measure,
    306	.report_progress = hits_drops_report_progress,
    307	.report_final = hits_drops_report_final,
    308};
    309
    310const struct bench bench_trig_uprobe_without_nop = {
    311	.name = "trig-uprobe-without-nop",
    312	.setup = uprobe_setup_without_nop,
    313	.producer_thread = uprobe_producer_without_nop,
    314	.consumer_thread = trigger_consumer,
    315	.measure = trigger_measure,
    316	.report_progress = hits_drops_report_progress,
    317	.report_final = hits_drops_report_final,
    318};
    319
    320const struct bench bench_trig_uretprobe_without_nop = {
    321	.name = "trig-uretprobe-without-nop",
    322	.setup = uretprobe_setup_without_nop,
    323	.producer_thread = uprobe_producer_without_nop,
    324	.consumer_thread = trigger_consumer,
    325	.measure = trigger_measure,
    326	.report_progress = hits_drops_report_progress,
    327	.report_final = hits_drops_report_final,
    328};