cmpxchg8b_emu.S 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. #include <linux/export.h>
  3. #include <linux/linkage.h>
  4. #include <asm/percpu.h>
  5. #include <asm/processor-flags.h>
  6. .text
  7. #ifndef CONFIG_X86_CMPXCHG64
  8. /*
  9. * Emulate 'cmpxchg8b (%esi)' on UP
  10. *
  11. * Inputs:
  12. * %esi : memory location to compare
  13. * %eax : low 32 bits of old value
  14. * %edx : high 32 bits of old value
  15. * %ebx : low 32 bits of new value
  16. * %ecx : high 32 bits of new value
  17. */
  18. SYM_FUNC_START(cmpxchg8b_emu)
  19. pushfl
  20. cli
  21. cmpl (%esi), %eax
  22. jne .Lnot_same
  23. cmpl 4(%esi), %edx
  24. jne .Lnot_same
  25. movl %ebx, (%esi)
  26. movl %ecx, 4(%esi)
  27. orl $X86_EFLAGS_ZF, (%esp)
  28. popfl
  29. RET
  30. .Lnot_same:
  31. movl (%esi), %eax
  32. movl 4(%esi), %edx
  33. andl $(~X86_EFLAGS_ZF), (%esp)
  34. popfl
  35. RET
  36. SYM_FUNC_END(cmpxchg8b_emu)
  37. EXPORT_SYMBOL(cmpxchg8b_emu)
  38. #endif
  39. #ifndef CONFIG_UML
  40. /*
  41. * Emulate 'cmpxchg8b %fs:(%rsi)'
  42. *
  43. * Inputs:
  44. * %esi : memory location to compare
  45. * %eax : low 32 bits of old value
  46. * %edx : high 32 bits of old value
  47. * %ebx : low 32 bits of new value
  48. * %ecx : high 32 bits of new value
  49. *
  50. * Notably this is not LOCK prefixed and is not safe against NMIs
  51. */
  52. SYM_FUNC_START(this_cpu_cmpxchg8b_emu)
  53. pushfl
  54. cli
  55. cmpl __percpu (%esi), %eax
  56. jne .Lnot_same2
  57. cmpl __percpu 4(%esi), %edx
  58. jne .Lnot_same2
  59. movl %ebx, __percpu (%esi)
  60. movl %ecx, __percpu 4(%esi)
  61. orl $X86_EFLAGS_ZF, (%esp)
  62. popfl
  63. RET
  64. .Lnot_same2:
  65. movl __percpu (%esi), %eax
  66. movl __percpu 4(%esi), %edx
  67. andl $(~X86_EFLAGS_ZF), (%esp)
  68. popfl
  69. RET
  70. SYM_FUNC_END(this_cpu_cmpxchg8b_emu)
  71. #endif