Exception.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* This Hello World simply print out "Hello World" */
  4. #include <stdatomic.h>
  5. #include <inttypes.h>
  6. #include "pal.h"
  7. #include "pal_debug.h"
  8. void handler1 (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
  9. {
  10. pal_printf("Arithmetic Exception Handler 1: 0x%08lx, rip = 0x%08lx\n",
  11. arg, context->rip);
  12. while (*(unsigned char *) context->rip != 0x90)
  13. context->rip++;
  14. DkExceptionReturn(event);
  15. }
  16. void handler2 (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
  17. {
  18. pal_printf("Arithmetic Exception Handler 2: 0x%08lx, rip = 0x%08lx\n",
  19. arg, context->rip);
  20. while (*(unsigned char *) context->rip != 0x90)
  21. context->rip++;
  22. DkExceptionReturn(event);
  23. }
  24. void handler3 (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
  25. {
  26. pal_printf("Memory Fault Exception Handler: 0x%08lx, rip = 0x%08lx\n",
  27. arg, context->rip);
  28. while (*(unsigned char *) context->rip != 0x90)
  29. context->rip++;
  30. DkExceptionReturn(event);
  31. }
  32. atomic_bool handler4_called = false;
  33. void handler4(PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
  34. {
  35. pal_printf("Arithmetic Exception Handler 4: 0x%" PRIx64 ", rip = 0x%" PRIx64 "\n", arg, context->rip);
  36. while (*(unsigned char *) context->rip != 0x90)
  37. context->rip++;
  38. handler4_called = true;
  39. DkExceptionReturn(event);
  40. }
  41. static void red_zone_test() {
  42. uint64_t res = 0;
  43. // First call some function to ensure that gcc doesn't use the red zone
  44. // itself.
  45. pal_printf("Testing red zone...\n");
  46. __asm__ volatile (
  47. // Fill the red zone with a pattern (0xaa 0xa9 0xa8 ...)
  48. "movq $-128, %%rax\n"
  49. "movq $0xaa, %%rbx\n"
  50. "1:\n"
  51. "movb %%bl, (%%rsp, %%rax, 1)\n"
  52. "decq %%rbx\n"
  53. "incq %%rax\n"
  54. "jnz 1b\n"
  55. // Trigger exception
  56. "movq $1, %%rax\n"
  57. "cqo\n"
  58. "movq $0, %%rbx\n"
  59. "divq %%rbx\n"
  60. "nop\n"
  61. // Calculate sum of pattern
  62. "movq $-128, %%rax\n"
  63. "movq $0, %%rbx\n"
  64. "movq $0, %%rcx\n"
  65. "1:\n"
  66. "movb (%%rsp, %%rax, 1), %%bl\n"
  67. "addq %%rbx, %%rcx\n"
  68. "incq %%rax\n"
  69. "jnz 1b\n"
  70. "movq %%rcx, %q0\n"
  71. : "=rm"(res)
  72. :
  73. : "rax", "rbx", "rcx", "rdx", "cc", "memory");
  74. if (!handler4_called) {
  75. pal_printf("Exception handler was not called!\n");
  76. return;
  77. }
  78. if (res != 13632) {
  79. pal_printf("Sum over red zone (%lu) doesn't match!\n", res);
  80. return;
  81. }
  82. pal_printf("Red zone test ok.\n");
  83. }
  84. int main (void)
  85. {
  86. volatile long i;
  87. DkSetExceptionHandler(handler1, PAL_EVENT_ARITHMETIC_ERROR);
  88. i = 0;
  89. i = 1 / i;
  90. __asm__ volatile("nop");
  91. DkSetExceptionHandler(handler2, PAL_EVENT_ARITHMETIC_ERROR);
  92. i = 0;
  93. i = 1 / i;
  94. __asm__ volatile("nop");
  95. DkSetExceptionHandler(handler3, PAL_EVENT_MEMFAULT);
  96. *(volatile long *) 0x1000 = 0;
  97. __asm__ volatile("nop");
  98. DkSetExceptionHandler(handler4, PAL_EVENT_ARITHMETIC_ERROR);
  99. red_zone_test();
  100. return 0;
  101. }