octeon-crypto.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2004-2012 Cavium Networks
  7. */
  8. #include <asm/cop2.h>
  9. #include <linux/export.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/sched/task_stack.h>
  12. #include "octeon-crypto.h"
  13. /**
  14. * Enable access to Octeon's COP2 crypto hardware for kernel use. Wrap any
  15. * crypto operations in calls to octeon_crypto_enable/disable in order to make
  16. * sure the state of COP2 isn't corrupted if userspace is also performing
  17. * hardware crypto operations. Allocate the state parameter on the stack.
  18. * Returns with preemption disabled.
  19. *
  20. * @state: Pointer to state structure to store current COP2 state in.
  21. *
  22. * Returns: Flags to be passed to octeon_crypto_disable()
  23. */
  24. unsigned long octeon_crypto_enable(struct octeon_cop2_state *state)
  25. {
  26. int status;
  27. unsigned long flags;
  28. preempt_disable();
  29. local_irq_save(flags);
  30. status = read_c0_status();
  31. write_c0_status(status | ST0_CU2);
  32. if (KSTK_STATUS(current) & ST0_CU2) {
  33. octeon_cop2_save(&(current->thread.cp2));
  34. KSTK_STATUS(current) &= ~ST0_CU2;
  35. status &= ~ST0_CU2;
  36. } else if (status & ST0_CU2) {
  37. octeon_cop2_save(state);
  38. }
  39. local_irq_restore(flags);
  40. return status & ST0_CU2;
  41. }
  42. EXPORT_SYMBOL_GPL(octeon_crypto_enable);
  43. /**
  44. * Disable access to Octeon's COP2 crypto hardware in the kernel. This must be
  45. * called after an octeon_crypto_enable() before any context switch or return to
  46. * userspace.
  47. *
  48. * @state: Pointer to COP2 state to restore
  49. * @flags: Return value from octeon_crypto_enable()
  50. */
  51. void octeon_crypto_disable(struct octeon_cop2_state *state,
  52. unsigned long crypto_flags)
  53. {
  54. unsigned long flags;
  55. local_irq_save(flags);
  56. if (crypto_flags & ST0_CU2)
  57. octeon_cop2_restore(state);
  58. else
  59. write_c0_status(read_c0_status() & ~ST0_CU2);
  60. local_irq_restore(flags);
  61. preempt_enable();
  62. }
  63. EXPORT_SYMBOL_GPL(octeon_crypto_disable);