fpustate.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include <u.h>
  2. #include <libc.h>
  3. // Test that the FPU state is correctly saved and available in the /proc/<pid>/fpregs
  4. void
  5. pass(void) {
  6. print("PASS\n");
  7. exits("PASS");
  8. }
  9. void
  10. fail(const char *msg) {
  11. print("FAIL - %s\n", msg);
  12. exits("FAIL");
  13. }
  14. void
  15. main(void)
  16. {
  17. int childpid = fork();
  18. if (childpid > 0) {
  19. // Sleep a little to ensure the child is in the infinite loop,
  20. // then read the fpregs and kill the child
  21. const char *path = smprint("/proc/%d/ctl", childpid);
  22. int ctlfd = open(path, OWRITE);
  23. if (ctlfd < 0) {
  24. fprint(ctlfd, "kill");
  25. fail("Can't open ctl");
  26. }
  27. sleep(1000);
  28. path = smprint("/proc/%d/fpregs", childpid);
  29. int fpfd = open(path, OREAD);
  30. if (fpfd < 0) {
  31. fprint(ctlfd, "kill");
  32. fail("Can't open fpregs");
  33. }
  34. // Read fpregs - it would be better to read individual registers
  35. // from the file system - update this when it happens
  36. const int buflen = 512;
  37. char fpregbuf[buflen];
  38. if (pread(fpfd, fpregbuf, buflen, 0) < buflen) {
  39. fprint(ctlfd, "kill");
  40. fail("Can't read fpregs");
  41. }
  42. // xmm0 starts at 160, each xmm reg at 16 byte increments
  43. int xmm0 = *(int*)(fpregbuf + 160);
  44. int xmm1 = *(int*)(fpregbuf + 176);
  45. int xmm2 = *(int*)(fpregbuf + 192);
  46. int xmm3 = *(int*)(fpregbuf + 208);
  47. if (xmm0 != 1 && xmm1 != 2 && xmm2 != 3 && xmm3 != 4) {
  48. fprint(ctlfd, "kill");
  49. fail("unexpected values in child's fpreg buffer");
  50. }
  51. fprint(ctlfd, "kill");
  52. pass();
  53. } else if (childpid == 0) {
  54. // In child
  55. // Set some xmm variables then run a tight loop waiting for
  56. // the parent to read the fpregs and kill the child
  57. __asm__ __volatile__(
  58. "movq $1, %%rax;"
  59. "movq %%rax, %%xmm0;"
  60. "movq $2, %%rax;"
  61. "movq %%rax, %%xmm1;"
  62. "movq $3, %%rax;"
  63. "movq %%rax, %%xmm2;"
  64. "movq $4, %%rax;"
  65. "movq %%rax, %%xmm3;"
  66. "loop:"
  67. "jmp loop;"
  68. : : : "rax", "xmm0", "xmm1", "xmm2", "xmm3");
  69. fail("Somehow exited the asm loop");
  70. } else {
  71. // Error
  72. fail("fork failed");
  73. }
  74. }