Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[linux-6.6.y] Add support for Zhaoxin HW Random Number Generator #257

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions drivers/char/hw_random/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ config HW_RANDOM_VIA

If unsure, say Y.

config HW_RANDOM_ZHAOXIN
tristate "Zhaoxin HW Random Number Generator support"
depends on X86
default HW_RANDOM
help
This driver provides kernel-side support for the Random Number
Generator hardware found on Zhaoxin based motherboards.

To compile this driver as a module, choose M here: the
module will be called zhaoxin-rng.

If unsure, say Y.

config HW_RANDOM_IXP4XX
tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
depends on ARCH_IXP4XX || COMPILE_TEST
Expand Down
1 change: 1 addition & 0 deletions drivers/char/hw_random/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
n2-rng-y := n2-drv.o n2-asm.o
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
obj-$(CONFIG_HW_RANDOM_ZHAOXIN) += zhaoxin-rng.o
obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-trng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
Expand Down
23 changes: 10 additions & 13 deletions drivers/char/hw_random/via-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@
#include <asm/cpufeature.h>
#include <asm/fpu/api.h>




enum {
VIA_STRFILT_CNT_SHIFT = 16,
VIA_STRFILT_FAIL = (1 << 15),
Expand Down Expand Up @@ -135,7 +132,7 @@ static int via_rng_init(struct hwrng *rng)
* is always enabled if CPUID rng_en is set. There is no
* RNG configuration like it used to be the case in this
* register */
if (((c->x86 == 6) && (c->x86_model >= 0x0f)) || (c->x86 > 6)){
if ((c->x86 == 6) && (c->x86_model >= 0x0f)) {
if (!boot_cpu_has(X86_FEATURE_XSTORE_EN)) {
pr_err(PFX "can't enable hardware RNG "
"if XSTORE is not enabled\n");
Expand Down Expand Up @@ -191,19 +188,25 @@ static struct hwrng via_rng = {
.data_read = via_rng_data_read,
};

static const struct x86_cpu_id via_rng_cpu_ids[] = {
X86_MATCH_VENDOR_FAM_FEATURE(CENTAUR, 6, X86_FEATURE_XSTORE, NULL),
{}
};
MODULE_DEVICE_TABLE(x86cpu, via_rng_cpu_ids);

static int __init via_rng_mod_init(void)
{
int err;

if (!boot_cpu_has(X86_FEATURE_XSTORE))
if (!x86_match_cpu(via_rng_cpu_ids)) {
pr_err(PFX "The CPU isn't support XSTORE.\n");
return -ENODEV;
}

pr_info("VIA RNG detected\n");
err = hwrng_register(&via_rng);
if (err) {
pr_err(PFX "RNG registering failed (%d)\n",
err);
pr_err(PFX "RNG registering failed (%d)\n", err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里为什么要修改

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里修改的原因是,checkpatch.pl会提示格式warning。不过,这边会恢复保留原先格式。

goto out;
}
out:
Expand All @@ -217,11 +220,5 @@ static void __exit via_rng_mod_exit(void)
}
module_exit(via_rng_mod_exit);

static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = {
X86_MATCH_FEATURE(X86_FEATURE_XSTORE, NULL),
{}
};
MODULE_DEVICE_TABLE(x86cpu, via_rng_cpu_id);

MODULE_DESCRIPTION("H/W RNG driver for VIA CPU with PadLock");
MODULE_LICENSE("GPL");
95 changes: 95 additions & 0 deletions drivers/char/hw_random/zhaoxin-rng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0
/*
* RNG driver for Zhaoxin RNGs
*
* Copyright 2023 (c) Zhaoxin Semiconductor Co., Ltd
*/

#include <crypto/padlock.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/cpufeature.h>
#include <asm/cpu_device_id.h>
#include <asm/fpu/api.h>

enum {
ZHAOXIN_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
ZHAOXIN_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */
ZHAOXIN_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */
ZHAOXIN_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */
ZHAOXIN_RNG_MAX_SIZE = (128 * 1024),
};

static int zhaoxin_rng_init(struct hwrng *rng)
{
if (!boot_cpu_has(X86_FEATURE_XSTORE_EN)) {
pr_err(PFX "can't enable hardware RNG if XSTORE is not enabled\n");
return -ENODEV;
}

return 0;
}

static inline int rep_xstore(size_t size, size_t factor, void *result)
{
asm(".byte 0xf3, 0x0f, 0xa7, 0xc0"
: "=m"(*(size_t *)result), "+c"(size), "+d"(factor), "+D"(result));

return 0;
}

static int zhaoxin_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
if (max > ZHAOXIN_RNG_MAX_SIZE)
max = ZHAOXIN_RNG_MAX_SIZE;

rep_xstore(max, ZHAOXIN_RNG_CHUNK_1, data);

return max;
}

static struct hwrng zhaoxin_rng = {
.name = "zhaoxin",
.init = zhaoxin_rng_init,
.read = zhaoxin_rng_read,
};

static const struct x86_cpu_id zhaoxin_rng_cpu_ids[] = {
X86_MATCH_VENDOR_FAM_FEATURE(ZHAOXIN, 6, X86_FEATURE_XSTORE, NULL),
X86_MATCH_VENDOR_FAM_FEATURE(ZHAOXIN, 7, X86_FEATURE_XSTORE, NULL),
X86_MATCH_VENDOR_FAM_FEATURE(CENTAUR, 7, X86_FEATURE_XSTORE, NULL),
{}
};
MODULE_DEVICE_TABLE(x86cpu, zhaoxin_rng_cpu_ids);

static int __init zhaoxin_rng_mod_init(void)
{
int err;

if (!x86_match_cpu(zhaoxin_rng_cpu_ids)) {
pr_err(PFX "The CPU isn't support XSTORE.\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个pr_err要修改成pr_info吧

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是参考同内核类似情况采用pr_err的。这边的理解是,要么使用pr_err,要么直接不打印任何信息。而改为pr_info的话,会导致在其他非zhaoxin_rng_cpu_ids列表中的处理器平台上会多出冗余打印信息。

return -ENODEV;
}

pr_info("Zhaoxin RNG detected\n");

err = hwrng_register(&zhaoxin_rng);
if (err)
pr_err(PFX "RNG registering failed (%d)\n", err);

return err;
}
module_init(zhaoxin_rng_mod_init);

static void __exit zhaoxin_rng_mod_exit(void)
{
hwrng_unregister(&zhaoxin_rng);
}
module_exit(zhaoxin_rng_mod_exit);

MODULE_DESCRIPTION("H/W RNG driver for Zhaoxin CPUs");
MODULE_AUTHOR("[email protected]");
MODULE_LICENSE("GPL");
Loading