linux/lib/test_static_keys.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Kernel module for testing static keys.
   4 *
   5 * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
   6 *
   7 * Authors:
   8 *      Jason Baron       <jbaron@akamai.com>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/jump_label.h>
  13
  14/* old keys */
  15struct static_key old_true_key  = STATIC_KEY_INIT_TRUE;
  16struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
  17
  18/* new api */
  19DEFINE_STATIC_KEY_TRUE(true_key);
  20DEFINE_STATIC_KEY_FALSE(false_key);
  21
  22/* external */
  23extern struct static_key base_old_true_key;
  24extern struct static_key base_inv_old_true_key;
  25extern struct static_key base_old_false_key;
  26extern struct static_key base_inv_old_false_key;
  27
  28/* new api */
  29extern struct static_key_true base_true_key;
  30extern struct static_key_true base_inv_true_key;
  31extern struct static_key_false base_false_key;
  32extern struct static_key_false base_inv_false_key;
  33
  34
  35struct test_key {
  36        bool                    init_state;
  37        struct static_key       *key;
  38        bool                    (*test_key)(void);
  39};
  40
  41#define test_key_func(key, branch)      \
  42static bool key ## _ ## branch(void)    \
  43{                                       \
  44        return branch(&key);            \
  45}
  46
  47static void invert_key(struct static_key *key)
  48{
  49        if (static_key_enabled(key))
  50                static_key_disable(key);
  51        else
  52                static_key_enable(key);
  53}
  54
  55static void invert_keys(struct test_key *keys, int size)
  56{
  57        struct static_key *previous = NULL;
  58        int i;
  59
  60        for (i = 0; i < size; i++) {
  61                if (previous != keys[i].key) {
  62                        invert_key(keys[i].key);
  63                        previous = keys[i].key;
  64                }
  65        }
  66}
  67
  68static int verify_keys(struct test_key *keys, int size, bool invert)
  69{
  70        int i;
  71        bool ret, init;
  72
  73        for (i = 0; i < size; i++) {
  74                ret = static_key_enabled(keys[i].key);
  75                init = keys[i].init_state;
  76                if (ret != (invert ? !init : init))
  77                        return -EINVAL;
  78                ret = keys[i].test_key();
  79                if (static_key_enabled(keys[i].key)) {
  80                        if (!ret)
  81                                return -EINVAL;
  82                } else {
  83                        if (ret)
  84                                return -EINVAL;
  85                }
  86        }
  87        return 0;
  88}
  89
  90test_key_func(old_true_key, static_key_true)
  91test_key_func(old_false_key, static_key_false)
  92test_key_func(true_key, static_branch_likely)
  93test_key_func(true_key, static_branch_unlikely)
  94test_key_func(false_key, static_branch_likely)
  95test_key_func(false_key, static_branch_unlikely)
  96test_key_func(base_old_true_key, static_key_true)
  97test_key_func(base_inv_old_true_key, static_key_true)
  98test_key_func(base_old_false_key, static_key_false)
  99test_key_func(base_inv_old_false_key, static_key_false)
 100test_key_func(base_true_key, static_branch_likely)
 101test_key_func(base_true_key, static_branch_unlikely)
 102test_key_func(base_inv_true_key, static_branch_likely)
 103test_key_func(base_inv_true_key, static_branch_unlikely)
 104test_key_func(base_false_key, static_branch_likely)
 105test_key_func(base_false_key, static_branch_unlikely)
 106test_key_func(base_inv_false_key, static_branch_likely)
 107test_key_func(base_inv_false_key, static_branch_unlikely)
 108
 109static int __init test_static_key_init(void)
 110{
 111        int ret;
 112        int size;
 113
 114        struct test_key static_key_tests[] = {
 115                /* internal keys - old keys */
 116                {
 117                        .init_state     = true,
 118                        .key            = &old_true_key,
 119                        .test_key       = &old_true_key_static_key_true,
 120                },
 121                {
 122                        .init_state     = false,
 123                        .key            = &old_false_key,
 124                        .test_key       = &old_false_key_static_key_false,
 125                },
 126                /* internal keys - new keys */
 127                {
 128                        .init_state     = true,
 129                        .key            = &true_key.key,
 130                        .test_key       = &true_key_static_branch_likely,
 131                },
 132                {
 133                        .init_state     = true,
 134                        .key            = &true_key.key,
 135                        .test_key       = &true_key_static_branch_unlikely,
 136                },
 137                {
 138                        .init_state     = false,
 139                        .key            = &false_key.key,
 140                        .test_key       = &false_key_static_branch_likely,
 141                },
 142                {
 143                        .init_state     = false,
 144                        .key            = &false_key.key,
 145                        .test_key       = &false_key_static_branch_unlikely,
 146                },
 147                /* external keys - old keys */
 148                {
 149                        .init_state     = true,
 150                        .key            = &base_old_true_key,
 151                        .test_key       = &base_old_true_key_static_key_true,
 152                },
 153                {
 154                        .init_state     = false,
 155                        .key            = &base_inv_old_true_key,
 156                        .test_key       = &base_inv_old_true_key_static_key_true,
 157                },
 158                {
 159                        .init_state     = false,
 160                        .key            = &base_old_false_key,
 161                        .test_key       = &base_old_false_key_static_key_false,
 162                },
 163                {
 164                        .init_state     = true,
 165                        .key            = &base_inv_old_false_key,
 166                        .test_key       = &base_inv_old_false_key_static_key_false,
 167                },
 168                /* external keys - new keys */
 169                {
 170                        .init_state     = true,
 171                        .key            = &base_true_key.key,
 172                        .test_key       = &base_true_key_static_branch_likely,
 173                },
 174                {
 175                        .init_state     = true,
 176                        .key            = &base_true_key.key,
 177                        .test_key       = &base_true_key_static_branch_unlikely,
 178                },
 179                {
 180                        .init_state     = false,
 181                        .key            = &base_inv_true_key.key,
 182                        .test_key       = &base_inv_true_key_static_branch_likely,
 183                },
 184                {
 185                        .init_state     = false,
 186                        .key            = &base_inv_true_key.key,
 187                        .test_key       = &base_inv_true_key_static_branch_unlikely,
 188                },
 189                {
 190                        .init_state     = false,
 191                        .key            = &base_false_key.key,
 192                        .test_key       = &base_false_key_static_branch_likely,
 193                },
 194                {
 195                        .init_state     = false,
 196                        .key            = &base_false_key.key,
 197                        .test_key       = &base_false_key_static_branch_unlikely,
 198                },
 199                {
 200                        .init_state     = true,
 201                        .key            = &base_inv_false_key.key,
 202                        .test_key       = &base_inv_false_key_static_branch_likely,
 203                },
 204                {
 205                        .init_state     = true,
 206                        .key            = &base_inv_false_key.key,
 207                        .test_key       = &base_inv_false_key_static_branch_unlikely,
 208                },
 209        };
 210
 211        size = ARRAY_SIZE(static_key_tests);
 212
 213        ret = verify_keys(static_key_tests, size, false);
 214        if (ret)
 215                goto out;
 216
 217        invert_keys(static_key_tests, size);
 218        ret = verify_keys(static_key_tests, size, true);
 219        if (ret)
 220                goto out;
 221
 222        invert_keys(static_key_tests, size);
 223        ret = verify_keys(static_key_tests, size, false);
 224        if (ret)
 225                goto out;
 226        return 0;
 227out:
 228        return ret;
 229}
 230
 231static void __exit test_static_key_exit(void)
 232{
 233}
 234
 235module_init(test_static_key_init);
 236module_exit(test_static_key_exit);
 237
 238MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
 239MODULE_LICENSE("GPL");
 240