Back to home page

LXR

 
 

    


0001 /*
0002  * Kernel module for testing static keys.
0003  *
0004  * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
0005  *
0006  * Authors:
0007  *      Jason Baron       <jbaron@akamai.com>
0008  *
0009  * This software is licensed under the terms of the GNU General Public
0010  * License version 2, as published by the Free Software Foundation, and
0011  * may be copied, distributed, and modified under those terms.
0012  *
0013  * This program is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016  * GNU General Public License for more details.
0017  */
0018 
0019 #include <linux/module.h>
0020 #include <linux/jump_label.h>
0021 
0022 /* old keys */
0023 struct static_key old_true_key  = STATIC_KEY_INIT_TRUE;
0024 struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
0025 
0026 /* new api */
0027 DEFINE_STATIC_KEY_TRUE(true_key);
0028 DEFINE_STATIC_KEY_FALSE(false_key);
0029 
0030 /* external */
0031 extern struct static_key base_old_true_key;
0032 extern struct static_key base_inv_old_true_key;
0033 extern struct static_key base_old_false_key;
0034 extern struct static_key base_inv_old_false_key;
0035 
0036 /* new api */
0037 extern struct static_key_true base_true_key;
0038 extern struct static_key_true base_inv_true_key;
0039 extern struct static_key_false base_false_key;
0040 extern struct static_key_false base_inv_false_key;
0041 
0042 
0043 struct test_key {
0044     bool            init_state;
0045     struct static_key   *key;
0046     bool            (*test_key)(void);
0047 };
0048 
0049 #define test_key_func(key, branch)  \
0050 static bool key ## _ ## branch(void)    \
0051 {                   \
0052     return branch(&key);        \
0053 }
0054 
0055 static void invert_key(struct static_key *key)
0056 {
0057     if (static_key_enabled(key))
0058         static_key_disable(key);
0059     else
0060         static_key_enable(key);
0061 }
0062 
0063 static void invert_keys(struct test_key *keys, int size)
0064 {
0065     struct static_key *previous = NULL;
0066     int i;
0067 
0068     for (i = 0; i < size; i++) {
0069         if (previous != keys[i].key) {
0070             invert_key(keys[i].key);
0071             previous = keys[i].key;
0072         }
0073     }
0074 }
0075 
0076 static int verify_keys(struct test_key *keys, int size, bool invert)
0077 {
0078     int i;
0079     bool ret, init;
0080 
0081     for (i = 0; i < size; i++) {
0082         ret = static_key_enabled(keys[i].key);
0083         init = keys[i].init_state;
0084         if (ret != (invert ? !init : init))
0085             return -EINVAL;
0086         ret = keys[i].test_key();
0087         if (static_key_enabled(keys[i].key)) {
0088             if (!ret)
0089                 return -EINVAL;
0090         } else {
0091             if (ret)
0092                 return -EINVAL;
0093         }
0094     }
0095     return 0;
0096 }
0097 
0098 test_key_func(old_true_key, static_key_true)
0099 test_key_func(old_false_key, static_key_false)
0100 test_key_func(true_key, static_branch_likely)
0101 test_key_func(true_key, static_branch_unlikely)
0102 test_key_func(false_key, static_branch_likely)
0103 test_key_func(false_key, static_branch_unlikely)
0104 test_key_func(base_old_true_key, static_key_true)
0105 test_key_func(base_inv_old_true_key, static_key_true)
0106 test_key_func(base_old_false_key, static_key_false)
0107 test_key_func(base_inv_old_false_key, static_key_false)
0108 test_key_func(base_true_key, static_branch_likely)
0109 test_key_func(base_true_key, static_branch_unlikely)
0110 test_key_func(base_inv_true_key, static_branch_likely)
0111 test_key_func(base_inv_true_key, static_branch_unlikely)
0112 test_key_func(base_false_key, static_branch_likely)
0113 test_key_func(base_false_key, static_branch_unlikely)
0114 test_key_func(base_inv_false_key, static_branch_likely)
0115 test_key_func(base_inv_false_key, static_branch_unlikely)
0116 
0117 static int __init test_static_key_init(void)
0118 {
0119     int ret;
0120     int size;
0121 
0122     struct test_key static_key_tests[] = {
0123         /* internal keys - old keys */
0124         {
0125             .init_state = true,
0126             .key        = &old_true_key,
0127             .test_key   = &old_true_key_static_key_true,
0128         },
0129         {
0130             .init_state = false,
0131             .key        = &old_false_key,
0132             .test_key   = &old_false_key_static_key_false,
0133         },
0134         /* internal keys - new keys */
0135         {
0136             .init_state = true,
0137             .key        = &true_key.key,
0138             .test_key   = &true_key_static_branch_likely,
0139         },
0140         {
0141             .init_state = true,
0142             .key        = &true_key.key,
0143             .test_key   = &true_key_static_branch_unlikely,
0144         },
0145         {
0146             .init_state = false,
0147             .key        = &false_key.key,
0148             .test_key   = &false_key_static_branch_likely,
0149         },
0150         {
0151             .init_state = false,
0152             .key        = &false_key.key,
0153             .test_key   = &false_key_static_branch_unlikely,
0154         },
0155         /* external keys - old keys */
0156         {
0157             .init_state = true,
0158             .key        = &base_old_true_key,
0159             .test_key   = &base_old_true_key_static_key_true,
0160         },
0161         {
0162             .init_state = false,
0163             .key        = &base_inv_old_true_key,
0164             .test_key   = &base_inv_old_true_key_static_key_true,
0165         },
0166         {
0167             .init_state = false,
0168             .key        = &base_old_false_key,
0169             .test_key   = &base_old_false_key_static_key_false,
0170         },
0171         {
0172             .init_state = true,
0173             .key        = &base_inv_old_false_key,
0174             .test_key   = &base_inv_old_false_key_static_key_false,
0175         },
0176         /* external keys - new keys */
0177         {
0178             .init_state = true,
0179             .key        = &base_true_key.key,
0180             .test_key   = &base_true_key_static_branch_likely,
0181         },
0182         {
0183             .init_state = true,
0184             .key        = &base_true_key.key,
0185             .test_key   = &base_true_key_static_branch_unlikely,
0186         },
0187         {
0188             .init_state = false,
0189             .key        = &base_inv_true_key.key,
0190             .test_key   = &base_inv_true_key_static_branch_likely,
0191         },
0192         {
0193             .init_state = false,
0194             .key        = &base_inv_true_key.key,
0195             .test_key   = &base_inv_true_key_static_branch_unlikely,
0196         },
0197         {
0198             .init_state = false,
0199             .key        = &base_false_key.key,
0200             .test_key   = &base_false_key_static_branch_likely,
0201         },
0202         {
0203             .init_state = false,
0204             .key        = &base_false_key.key,
0205             .test_key   = &base_false_key_static_branch_unlikely,
0206         },
0207         {
0208             .init_state = true,
0209             .key        = &base_inv_false_key.key,
0210             .test_key   = &base_inv_false_key_static_branch_likely,
0211         },
0212         {
0213             .init_state = true,
0214             .key        = &base_inv_false_key.key,
0215             .test_key   = &base_inv_false_key_static_branch_unlikely,
0216         },
0217     };
0218 
0219     size = ARRAY_SIZE(static_key_tests);
0220 
0221     ret = verify_keys(static_key_tests, size, false);
0222     if (ret)
0223         goto out;
0224 
0225     invert_keys(static_key_tests, size);
0226     ret = verify_keys(static_key_tests, size, true);
0227     if (ret)
0228         goto out;
0229 
0230     invert_keys(static_key_tests, size);
0231     ret = verify_keys(static_key_tests, size, false);
0232     if (ret)
0233         goto out;
0234     return 0;
0235 out:
0236     return ret;
0237 }
0238 
0239 static void __exit test_static_key_exit(void)
0240 {
0241 }
0242 
0243 module_init(test_static_key_init);
0244 module_exit(test_static_key_exit);
0245 
0246 MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
0247 MODULE_LICENSE("GPL");