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

xor.c (3843B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * xor.c : Multiple Devices driver for Linux
      4 *
      5 * Copyright (C) 1996, 1997, 1998, 1999, 2000,
      6 * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
      7 *
      8 * Dispatch optimized RAID-5 checksumming functions.
      9 */
     10
     11#define BH_TRACE 0
     12#include <linux/module.h>
     13#include <linux/gfp.h>
     14#include <linux/raid/xor.h>
     15#include <linux/jiffies.h>
     16#include <linux/preempt.h>
     17#include <asm/xor.h>
     18
     19#ifndef XOR_SELECT_TEMPLATE
     20#define XOR_SELECT_TEMPLATE(x) (x)
     21#endif
     22
     23/* The xor routines to use.  */
     24static struct xor_block_template *active_template;
     25
     26void
     27xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
     28{
     29	unsigned long *p1, *p2, *p3, *p4;
     30
     31	p1 = (unsigned long *) srcs[0];
     32	if (src_count == 1) {
     33		active_template->do_2(bytes, dest, p1);
     34		return;
     35	}
     36
     37	p2 = (unsigned long *) srcs[1];
     38	if (src_count == 2) {
     39		active_template->do_3(bytes, dest, p1, p2);
     40		return;
     41	}
     42
     43	p3 = (unsigned long *) srcs[2];
     44	if (src_count == 3) {
     45		active_template->do_4(bytes, dest, p1, p2, p3);
     46		return;
     47	}
     48
     49	p4 = (unsigned long *) srcs[3];
     50	active_template->do_5(bytes, dest, p1, p2, p3, p4);
     51}
     52EXPORT_SYMBOL(xor_blocks);
     53
     54/* Set of all registered templates.  */
     55static struct xor_block_template *__initdata template_list;
     56
     57#ifndef MODULE
     58static void __init do_xor_register(struct xor_block_template *tmpl)
     59{
     60	tmpl->next = template_list;
     61	template_list = tmpl;
     62}
     63
     64static int __init register_xor_blocks(void)
     65{
     66	active_template = XOR_SELECT_TEMPLATE(NULL);
     67
     68	if (!active_template) {
     69#define xor_speed	do_xor_register
     70		// register all the templates and pick the first as the default
     71		XOR_TRY_TEMPLATES;
     72#undef xor_speed
     73		active_template = template_list;
     74	}
     75	return 0;
     76}
     77#endif
     78
     79#define BENCH_SIZE	4096
     80#define REPS		800U
     81
     82static void __init
     83do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
     84{
     85	int speed;
     86	int i, j;
     87	ktime_t min, start, diff;
     88
     89	tmpl->next = template_list;
     90	template_list = tmpl;
     91
     92	preempt_disable();
     93
     94	min = (ktime_t)S64_MAX;
     95	for (i = 0; i < 3; i++) {
     96		start = ktime_get();
     97		for (j = 0; j < REPS; j++) {
     98			mb(); /* prevent loop optimization */
     99			tmpl->do_2(BENCH_SIZE, b1, b2);
    100			mb();
    101		}
    102		diff = ktime_sub(ktime_get(), start);
    103		if (diff < min)
    104			min = diff;
    105	}
    106
    107	preempt_enable();
    108
    109	// bytes/ns == GB/s, multiply by 1000 to get MB/s [not MiB/s]
    110	if (!min)
    111		min = 1;
    112	speed = (1000 * REPS * BENCH_SIZE) / (unsigned int)ktime_to_ns(min);
    113	tmpl->speed = speed;
    114
    115	pr_info("   %-16s: %5d MB/sec\n", tmpl->name, speed);
    116}
    117
    118static int __init
    119calibrate_xor_blocks(void)
    120{
    121	void *b1, *b2;
    122	struct xor_block_template *f, *fastest;
    123
    124	fastest = XOR_SELECT_TEMPLATE(NULL);
    125
    126	if (fastest) {
    127		printk(KERN_INFO "xor: automatically using best "
    128				 "checksumming function   %-10s\n",
    129		       fastest->name);
    130		goto out;
    131	}
    132
    133	b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
    134	if (!b1) {
    135		printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
    136		return -ENOMEM;
    137	}
    138	b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
    139
    140	/*
    141	 * If this arch/cpu has a short-circuited selection, don't loop through
    142	 * all the possible functions, just test the best one
    143	 */
    144
    145#define xor_speed(templ)	do_xor_speed((templ), b1, b2)
    146
    147	printk(KERN_INFO "xor: measuring software checksum speed\n");
    148	template_list = NULL;
    149	XOR_TRY_TEMPLATES;
    150	fastest = template_list;
    151	for (f = fastest; f; f = f->next)
    152		if (f->speed > fastest->speed)
    153			fastest = f;
    154
    155	pr_info("xor: using function: %s (%d MB/sec)\n",
    156	       fastest->name, fastest->speed);
    157
    158#undef xor_speed
    159
    160	free_pages((unsigned long)b1, 2);
    161out:
    162	active_template = fastest;
    163	return 0;
    164}
    165
    166static __exit void xor_exit(void) { }
    167
    168MODULE_LICENSE("GPL");
    169
    170#ifndef MODULE
    171/* when built-in xor.o must initialize before drivers/md/md.o */
    172core_initcall(register_xor_blocks);
    173#endif
    174
    175module_init(calibrate_xor_blocks);
    176module_exit(xor_exit);