suspend.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /*
  2. * Suspend support specific for s390.
  3. *
  4. * Copyright IBM Corp. 2009
  5. *
  6. * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
  7. */
  8. #include <linux/suspend.h>
  9. #include <linux/reboot.h>
  10. #include <linux/pfn.h>
  11. #include <linux/mm.h>
  12. #include <asm/sections.h>
  13. #include <asm/system.h>
  14. #include <asm/ipl.h>
  15. /*
  16. * References to section boundaries
  17. */
  18. extern const void __nosave_begin, __nosave_end;
  19. /*
  20. * check if given pfn is in the 'nosave' or in the read only NSS section
  21. */
  22. int pfn_is_nosave(unsigned long pfn)
  23. {
  24. unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
  25. unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end))
  26. >> PAGE_SHIFT;
  27. unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
  28. unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
  29. if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
  30. return 1;
  31. if (pfn >= stext_pfn && pfn <= eshared_pfn) {
  32. if (ipl_info.type == IPL_TYPE_NSS)
  33. return 1;
  34. } else if ((tprot(pfn * PAGE_SIZE) && pfn > 0))
  35. return 1;
  36. return 0;
  37. }
  38. void save_processor_state(void)
  39. {
  40. /* swsusp_arch_suspend() actually saves all cpu register contents.
  41. * Machine checks must be disabled since swsusp_arch_suspend() stores
  42. * register contents to their lowcore save areas. That's the same
  43. * place where register contents on machine checks would be saved.
  44. * To avoid register corruption disable machine checks.
  45. * We must also disable machine checks in the new psw mask for
  46. * program checks, since swsusp_arch_suspend() may generate program
  47. * checks. Disabling machine checks for all other new psw masks is
  48. * just paranoia.
  49. */
  50. local_mcck_disable();
  51. /* Disable lowcore protection */
  52. __ctl_clear_bit(0,28);
  53. S390_lowcore.external_new_psw.mask &= ~PSW_MASK_MCHECK;
  54. S390_lowcore.svc_new_psw.mask &= ~PSW_MASK_MCHECK;
  55. S390_lowcore.io_new_psw.mask &= ~PSW_MASK_MCHECK;
  56. S390_lowcore.program_new_psw.mask &= ~PSW_MASK_MCHECK;
  57. }
  58. void restore_processor_state(void)
  59. {
  60. S390_lowcore.external_new_psw.mask |= PSW_MASK_MCHECK;
  61. S390_lowcore.svc_new_psw.mask |= PSW_MASK_MCHECK;
  62. S390_lowcore.io_new_psw.mask |= PSW_MASK_MCHECK;
  63. S390_lowcore.program_new_psw.mask |= PSW_MASK_MCHECK;
  64. /* Enable lowcore protection */
  65. __ctl_set_bit(0,28);
  66. local_mcck_enable();
  67. }