early_nobss.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright IBM Corp. 2007, 2018
  4. */
  5. /*
  6. * Early setup functions which may not rely on an initialized bss
  7. * section. The last thing that is supposed to happen here is
  8. * initialization of the bss section.
  9. */
  10. #include <linux/processor.h>
  11. #include <linux/string.h>
  12. #include <asm/sections.h>
  13. #include <asm/lowcore.h>
  14. #include <asm/setup.h>
  15. #include <asm/timex.h>
  16. #include "entry.h"
  17. static void __init reset_tod_clock(void)
  18. {
  19. u64 time;
  20. if (store_tod_clock(&time) == 0)
  21. return;
  22. /* TOD clock not running. Set the clock to Unix Epoch. */
  23. if (set_tod_clock(TOD_UNIX_EPOCH) != 0 || store_tod_clock(&time) != 0)
  24. disabled_wait(0);
  25. memset(tod_clock_base, 0, 16);
  26. *(__u64 *) &tod_clock_base[1] = TOD_UNIX_EPOCH;
  27. S390_lowcore.last_update_clock = TOD_UNIX_EPOCH;
  28. }
  29. static void __init rescue_initrd(void)
  30. {
  31. unsigned long min_initrd_addr = (unsigned long) _end + (4UL << 20);
  32. /*
  33. * Just like in case of IPL from VM reader we make sure there is a
  34. * gap of 4MB between end of kernel and start of initrd.
  35. * That way we can also be sure that saving an NSS will succeed,
  36. * which however only requires different segments.
  37. */
  38. if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD))
  39. return;
  40. if (!INITRD_START || !INITRD_SIZE)
  41. return;
  42. if (INITRD_START >= min_initrd_addr)
  43. return;
  44. memmove((void *) min_initrd_addr, (void *) INITRD_START, INITRD_SIZE);
  45. INITRD_START = min_initrd_addr;
  46. }
  47. static void __init clear_bss_section(void)
  48. {
  49. memset(__bss_start, 0, __bss_stop - __bss_start);
  50. }
  51. void __init startup_init_nobss(void)
  52. {
  53. reset_tod_clock();
  54. rescue_initrd();
  55. clear_bss_section();
  56. }