MODULE_AUTHOR("David S. Miller ");
MODULE_DESCRIPTION("Niagara2 RNG driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
/* The Niagara2 RNG provides a 64-bit read-only random number * register, plus a control register. Access to the RNG is * virtualized through the hypervisor so that both guests and control * nodes can access the device. * * The entropy source consists of raw entropy sources, each * constructed from a voltage controlled oscillator whose phase is * jittered by thermal noise sources. * * The oscillator in each of the three raw entropy sources run at * different frequencies. Normally, all three generator outputs are * gathered, xored together, and fed into a CRC circuit, the output of * which is the 64-bit read-only register. * * Some time is necessary for all the necessary entropy to build up * such that a full 64-bits of entropy are available in the register. * In normal operating mode (RNG_CTL_LFSR is set), the chip implements * an interlock which blocks register reads until sufficient entropy * is available. * * A control register is provided for adjusting various aspects of RNG * operation, and to enable diagnostic modes. Each of the three raw * entropy sources has an enable bit (RNG_CTL_ES{1,2,3}). Also * provided are fields for controlling the minimum time in cycles * between read accesses to the register (RNG_CTL_WAIT, this controls * the interlock described in the previous paragraph). * * The standard setting is to have the mode bit (RNG_CTL_LFSR) set, * all three entropy sources enabled, and the interlock time set * appropriately. * * The CRC polynomial used by the chip is: * * P(X) = x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + x46 + * x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + x28 + x25 + * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 * * The RNG_CTL_VCO value of each noise cell must be programmed * separately. This is why 4 control register values must be provided * to the hypervisor. During a write, the hypervisor writes them all, * one at a time, to the actual RNG_CTL register. The first three * values are used to setup the desired RNG_CTL_VCO for each entropy * source, for example: * * control 0: (1 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES1 * control 1: (2 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES2 * control 2: (3 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES3 * * And then the fourth value sets the final chip state and enables * desired.
*/
staticint n2rng_hv_err_trans(unsignedlong hv_err)
{ switch (hv_err) { case HV_EOK: return 0; case HV_EWOULDBLOCK: return -EAGAIN; case HV_ENOACCESS: return -EPERM; case HV_EIO: return -EIO; case HV_EBUSY: return -EBUSY; case HV_EBADALIGN: case HV_ENORADDR: return -EFAULT; default: return -EINVAL;
}
}
/* In multi-socket situations, the hypervisor might need to * queue up the RNG control register write if it's for a unit * that is on a cpu socket other than the one we are executing on. * * We poll here waiting for a successful read of that control * register to make sure the write has been actually performed.
*/ staticunsignedlong n2rng_control_settle_v2(struct n2rng *np, int unit)
{ unsignedlong ra = __pa(&np->scratch_control[0]);
return n2rng_generic_read_control_v2(ra, unit);
}
staticunsignedlong n2rng_write_ctl_one(struct n2rng *np, int unit, unsignedlong state, unsignedlong control_ra, unsignedlong watchdog_timeout, unsignedlong *ticks)
{ unsignedlong hv_err;
/* Just try to see if we can successfully access the control register * of the RNG on the domain on which we are currently executing.
*/ staticint n2rng_try_read_ctl(struct n2rng *np)
{ unsignedlong hv_err; unsignedlong x;
if (np->hvapi_major == 1) {
hv_err = sun4v_rng_get_diag_ctl();
} else { /* We purposefully give invalid arguments, HV_NOACCESS * is higher priority than the errors we'd get from * these other cases, and that's the error we are * truly interested in.
*/
hv_err = sun4v_rng_ctl_read_v2(0UL, ~0UL, &x, &x, &x, &x); switch (hv_err) { case HV_EWOULDBLOCK: case HV_ENOACCESS: break; default:
hv_err = HV_EOK; break;
}
}
return n2rng_hv_err_trans(hv_err);
}
static u64 n2rng_control_default(struct n2rng *np, int ctl)
{
u64 val = 0;
if (np->data->chip_version == 1) {
val = ((2 << RNG_v1_CTL_ASEL_SHIFT) |
(N2RNG_ACCUM_CYCLES_DEFAULT << RNG_v1_CTL_WAIT_SHIFT) |
RNG_CTL_LFSR);
switch (ctl) { case 0:
val |= (1 << RNG_v1_CTL_VCO_SHIFT) | RNG_CTL_ES1; break; case 1:
val |= (2 << RNG_v1_CTL_VCO_SHIFT) | RNG_CTL_ES2; break; case 2:
val |= (3 << RNG_v1_CTL_VCO_SHIFT) | RNG_CTL_ES3; break; case 3:
val |= RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3; break; default: break;
}
staticint n2rng_grab_diag_control(struct n2rng *np)
{ int i, busy_count, err = -ENODEV;
busy_count = 0; for (i = 0; i < 100; i++) {
err = n2rng_try_read_ctl(np); if (err != -EAGAIN) break;
if (++busy_count > 100) {
dev_err(&np->op->dev, "Grab diag control timeout.\n"); return -ENODEV;
}
udelay(1);
}
return err;
}
staticint n2rng_init_control(struct n2rng *np)
{ int err = n2rng_grab_diag_control(np);
/* Not in the control domain, that's OK we are only a consumer * of the RNG data, we don't setup and program it.
*/ if (err == -EPERM) return 0; if (err) return err;
if (!(np->flags & N2RNG_FLAG_READY)) {
len = 0;
} elseif (np->flags & N2RNG_FLAG_BUFFER_VALID) {
np->flags &= ~N2RNG_FLAG_BUFFER_VALID;
*data = np->buffer;
len = 4;
} else { int err = n2rng_generic_read_data(ra); if (!err) {
np->flags |= N2RNG_FLAG_BUFFER_VALID;
np->buffer = np->test_data >> 32;
*data = np->test_data & 0xffffffff;
len = 4;
} else {
dev_err(&np->op->dev, "RNG error, retesting\n");
np->flags &= ~N2RNG_FLAG_READY; if (!(np->flags & N2RNG_FLAG_SHUTDOWN))
schedule_delayed_work(&np->work, 0);
len = 0;
}
}
return len;
}
/* On a guest node, just make sure we can read random data properly. * If a control node reboots or reloads it's n2rng driver, this won't * work during that time. So we have to keep probing until the device * becomes usable.
*/ staticint n2rng_guest_check(struct n2rng *np)
{ unsignedlong ra = __pa(&np->test_data);
switch (np->data->id) { case N2_n2_rng: case N2_vf_rng: case N2_kt_rng: case N2_m4_rng: /* yes, m4 uses the old value */
val = RNG_v1_SELFTEST_VAL; break; default:
val = RNG_v2_SELFTEST_VAL; break;
}
matches = 0; for (limit = 0; limit < SELFTEST_LOOPS_MAX; limit++) {
matches += n2rng_test_buffer_find(np, val); if (matches >= SELFTEST_MATCH_GOAL) break;
val = advance_polynomial(SELFTEST_POLY, val, 1);
}
err = 0; if (limit >= SELFTEST_LOOPS_MAX) {
err = -ENODEV;
dev_err(&np->op->dev, "Selftest failed on unit %lu\n", unit);
n2rng_dump_test_buffer(np);
} else
dev_info(&np->op->dev, "Selftest passed on unit %lu\n", unit);
err = n2rng_entropy_diag_read(np, unit, np->test_control,
HV_RNG_STATE_HEALTHCHECK,
np->test_buffer, sizeof(np->test_buffer),
&np->units[unit].control[0],
np->hv_state); if (err) return err;
return n2rng_check_selftest_buffer(np, unit);
}
staticint n2rng_control_check(struct n2rng *np)
{ int i;
for (i = 0; i < np->num_units; i++) { int err = n2rng_control_selftest(np, i); if (err) return err;
} return 0;
}
/* The sanity checks passed, install the final configuration into the * chip, it's ready to use.
*/ staticint n2rng_control_configure_units(struct n2rng *np)
{ int unit, err;
err = 0; for (unit = 0; unit < np->num_units; unit++) { struct n2rng_unit *up = &np->units[unit]; unsignedlong ctl_ra = __pa(&up->control[0]); int esrc;
u64 base, shift;
/* XXX This isn't the best. We should fetch a bunch * XXX of words using each entropy source combined XXX * with each VCO setting, and see which combinations * XXX give the best random data.
*/ for (esrc = 0; esrc < 3; esrc++)
up->control[esrc] = base |
(esrc << shift) |
(RNG_CTL_ES1 << esrc);
up->control[3] = base |
(RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3);
err = n2rng_generic_write_control(np, ctl_ra, unit,
HV_RNG_STATE_CONFIGURED); if (err) break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.