From: H.J. Lu Date: Thu, 10 Dec 2020 02:14:24 +0000 (-0800) Subject: x86: Update user interrupt handler stack frame X-Git-Tag: basepoints/gcc-12~2318 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=078c7498908d9b74caff34d12099b5c85470e277;p=thirdparty%2Fgcc.git x86: Update user interrupt handler stack frame User interrupt handler stack frame is similar to exception interrupt handler stack frame. Instead of error code, the second argument is user interrupt request register vector. gcc/ PR target/98219 * config/i386/uintrintrin.h (__uintr_frame): Remove uirrv. gcc/testsuite/ PR target/98219 * gcc.dg/guality/pr98219-1.c: New test. * gcc.dg/guality/pr98219-2.c: Likewise. * gcc.dg/torture/pr98219-1.c: Likewise. * gcc.dg/torture/pr98219-2.c: Likewise. * gcc.target/i386/uintr-2.c: Scan "add[lq] $8, %[er]sp". (uword_t): New. (foo): Add a uword_t argument. (UINTR_hanlder): Likewise. * gcc.target/i386/uintr-3.c: Scan "add[lq] $8, %[er]sp". (uword_t): New. (UINTR_hanlder): Add a uword_t argument. * gcc.target/i386/uintr-4.c (uword_t): New. (UINTR_hanlder): Add a uword_t argument. * gcc.target/i386/uintr-5.c (uword_t): New. (UINTR_hanlder): Add a uword_t argument. --- diff --git a/gcc/config/i386/uintrintrin.h b/gcc/config/i386/uintrintrin.h index 991f64279716..4606caf8582d 100644 --- a/gcc/config/i386/uintrintrin.h +++ b/gcc/config/i386/uintrintrin.h @@ -38,9 +38,6 @@ struct __uintr_frame { - /* The position of the most significant bit set in user-interrupt - request register. */ - unsigned long long uirrv; /* RIP of the interrupted user process. */ unsigned long long rip; /* RFLAGS of the interrupted user process. */ diff --git a/gcc/testsuite/gcc.dg/guality/pr98219-1.c b/gcc/testsuite/gcc.dg/guality/pr98219-1.c new file mode 100644 index 000000000000..c9cb8a51b344 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr98219-1.c @@ -0,0 +1,49 @@ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */ +/* { dg-options "-g -muintr -mgeneral-regs-only" } */ + +#include + +extern void exit (int); +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + +#define UIRRV 0x12345670 +#define RIP 0x12345671 +#define RFLAGS 0x12345672 +#define RSP 0x12345673 + +#define STRING(x) XSTRING(x) +#define XSTRING(x) #x +#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) +#define ASMNAME2(prefix, cname) XSTRING (prefix) cname + +void +__attribute__((interrupt, used)) +fn (struct __uintr_frame *frame, uword_t uirrv) +{ + if (UIRRV != uirrv) /* BREAK */ + __builtin_abort (); + if (RIP != frame->rip) + __builtin_abort (); + if (RFLAGS != frame->rflags) + __builtin_abort (); + if (RSP != frame->rsp) + __builtin_abort (); + + exit (0); +} + +int +main () +{ + asm ("push $" STRING (RSP) "; \ + push $" STRING (RFLAGS) "; \ + push $" STRING (RIP) "; \ + push $" STRING (UIRRV) "; \ + jmp " ASMNAME ("fn")); + return 0; +} + +/* { dg-final { gdb-test 22 "uirrv" "0x12345670" } } */ +/* { dg-final { gdb-test 22 "frame->rip" "0x12345671" } } */ +/* { dg-final { gdb-test 22 "frame->rflags" "0x12345672" } } */ +/* { dg-final { gdb-test 22 "frame->rsp" "0x12345673" } } */ diff --git a/gcc/testsuite/gcc.dg/guality/pr98219-2.c b/gcc/testsuite/gcc.dg/guality/pr98219-2.c new file mode 100644 index 000000000000..1f74eb3a82c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr98219-2.c @@ -0,0 +1,63 @@ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */ +/* { dg-options "-g -muintr -mgeneral-regs-only" } */ + +#include + +extern void exit (int); +typedef unsigned int uword_t __attribute__ ((mode (__word__))); +typedef int aligned __attribute__((aligned(64))); + +#define UIRRV 0x12345670 +#define RIP 0x12345671 +#define RFLAGS 0x12345672 +#define RSP 0x12345673 + +#define STRING(x) XSTRING(x) +#define XSTRING(x) #x +#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) +#define ASMNAME2(prefix, cname) XSTRING (prefix) cname + +int +check_int (int *i, int align) +{ + *i = 20; + if ((((ptrdiff_t) i) & (align - 1)) != 0) + __builtin_abort (); + return *i; +} + +void +__attribute__((interrupt, used)) +fn (struct __uintr_frame *frame, uword_t uirrv) +{ + aligned i; + if (check_int (&i, __alignof__(i)) != i) + __builtin_abort (); + + if (UIRRV != uirrv) /* BREAK */ + __builtin_abort (); + if (RIP != frame->rip) + __builtin_abort (); + if (RFLAGS != frame->rflags) + __builtin_abort (); + if (RSP != frame->rsp) + __builtin_abort (); + + exit (0); +} + +int +main () +{ + asm ("push $" STRING (RSP) "; \ + push $" STRING (RFLAGS) "; \ + push $" STRING (RIP) "; \ + push $" STRING (UIRRV) "; \ + jmp " ASMNAME ("fn")); + return 0; +} + +/* { dg-final { gdb-test 34 "uirrv" "0x12345670" } } */ +/* { dg-final { gdb-test 34 "frame->rip" "0x12345671" } } */ +/* { dg-final { gdb-test 34 "frame->rflags" "0x12345672" } } */ +/* { dg-final { gdb-test 34 "frame->rsp" "0x12345673" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr98219-1.c b/gcc/testsuite/gcc.dg/torture/pr98219-1.c new file mode 100644 index 000000000000..89b5aa3b9cba --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr98219-1.c @@ -0,0 +1,45 @@ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */ +/* { dg-skip-if "PR81210 sp not aligned to 16 bytes" { *-*-darwin* } } */ +/* { dg-options "-muintr -mgeneral-regs-only" } */ + +#include + +extern void exit (int); +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + +#define UIRRV 0x12345670 +#define RIP 0x12345671 +#define RFLAGS 0x12345672 +#define RSP 0x12345673 + +#define STRING(x) XSTRING(x) +#define XSTRING(x) #x +#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) +#define ASMNAME2(prefix, cname) XSTRING (prefix) cname + +void +__attribute__((interrupt, used)) +fn (struct __uintr_frame *frame, uword_t uirrv) +{ + if (UIRRV != uirrv) + __builtin_abort (); + if (RIP != frame->rip) + __builtin_abort (); + if (RFLAGS != frame->rflags) + __builtin_abort (); + if (RSP != frame->rsp) + __builtin_abort (); + + exit (0); +} + +int +main () +{ + asm ("push $" STRING (RSP) "; \ + push $" STRING (RFLAGS) "; \ + push $" STRING (RIP) "; \ + push $" STRING (UIRRV) "; \ + jmp " ASMNAME ("fn")); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr98219-2.c b/gcc/testsuite/gcc.dg/torture/pr98219-2.c new file mode 100644 index 000000000000..c2f33f84f3e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr98219-2.c @@ -0,0 +1,59 @@ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */ +/* { dg-skip-if "PR81210 sp not aligned to 16 bytes" { *-*-darwin* } } */ +/* { dg-options "-muintr -mgeneral-regs-only" } */ + +#include + +extern void exit (int); +typedef unsigned int uword_t __attribute__ ((mode (__word__))); +typedef int aligned __attribute__((aligned(64))); + +#define UIRRV 0x12345670 +#define RIP 0x12345671 +#define RFLAGS 0x12345672 +#define RSP 0x12345673 + +#define STRING(x) XSTRING(x) +#define XSTRING(x) #x +#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) +#define ASMNAME2(prefix, cname) XSTRING (prefix) cname + +int +check_int (int *i, int align) +{ + *i = 20; + if ((((ptrdiff_t) i) & (align - 1)) != 0) + __builtin_abort (); + return *i; +} + +void +__attribute__((interrupt, used)) +fn (struct __uintr_frame *frame, uword_t uirrv) +{ + aligned i; + if (check_int (&i, __alignof__(i)) != i) + __builtin_abort (); + + if (UIRRV != uirrv) + __builtin_abort (); + if (RIP != frame->rip) + __builtin_abort (); + if (RFLAGS != frame->rflags) + __builtin_abort (); + if (RSP != frame->rsp) + __builtin_abort (); + + exit (0); +} + +int +main () +{ + asm ("push $" STRING (RSP) "; \ + push $" STRING (RFLAGS) "; \ + push $" STRING (RIP) "; \ + push $" STRING (UIRRV) "; \ + jmp " ASMNAME ("fn")); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/uintr-2.c b/gcc/testsuite/gcc.target/i386/uintr-2.c index e705732c1bd5..0a83c662b949 100644 --- a/gcc/testsuite/gcc.target/i386/uintr-2.c +++ b/gcc/testsuite/gcc.target/i386/uintr-2.c @@ -1,17 +1,20 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -muintr -mgeneral-regs-only" } */ /* { dg-final { scan-assembler-times "uiret" "2" } } */ +/* { dg-final { scan-assembler-times "add\[lq]\[ \t]\+\\\$8, %\[er\]sp" "2" } } */ #include +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + void __attribute__((interrupt)) -foo (void *frame) +foo (void *frame, uword_t uirrv) { } void __attribute__((interrupt)) -UINTR_hanlder (struct __uintr_frame *frame) +UINTR_hanlder (struct __uintr_frame *frame, uword_t uirrv) { } diff --git a/gcc/testsuite/gcc.target/i386/uintr-3.c b/gcc/testsuite/gcc.target/i386/uintr-3.c index d2843495158e..92476cfa45c1 100644 --- a/gcc/testsuite/gcc.target/i386/uintr-3.c +++ b/gcc/testsuite/gcc.target/i386/uintr-3.c @@ -1,9 +1,13 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -muintr" } */ /* { dg-final { scan-assembler "uiret" } } */ +/* { dg-final { scan-assembler "add\[lq]\[ \t]\+\\\$8, %\[er\]sp" } } */ + #include +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + void __attribute__ ((target("general-regs-only"), interrupt)) -UINTR_handler (struct __uintr_frame *p) +UINTR_handler (struct __uintr_frame *p, uword_t uirrv) { } diff --git a/gcc/testsuite/gcc.target/i386/uintr-4.c b/gcc/testsuite/gcc.target/i386/uintr-4.c index f3b371b42315..4d0ec34dfa0f 100644 --- a/gcc/testsuite/gcc.target/i386/uintr-4.c +++ b/gcc/testsuite/gcc.target/i386/uintr-4.c @@ -3,7 +3,9 @@ #include +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + void __attribute__ ((interrupt)) -UINTR_handler (struct __uintr_frame *p) -{ /* { dg-message "SSE instructions aren't allowed in an interrupt service routine" } */ +UINTR_handler (struct __uintr_frame *p, uword_t uirrv) +{ /* { dg-message "SSE instructions aren't allowed in an exception service routine" } */ } diff --git a/gcc/testsuite/gcc.target/i386/uintr-5.c b/gcc/testsuite/gcc.target/i386/uintr-5.c index ac44be0a7064..49cb2ec8097c 100644 --- a/gcc/testsuite/gcc.target/i386/uintr-5.c +++ b/gcc/testsuite/gcc.target/i386/uintr-5.c @@ -4,7 +4,9 @@ #include +typedef unsigned int uword_t __attribute__ ((mode (__word__))); + void -UINTR_hanlder (struct __uintr_frame *frame) +UINTR_hanlder (struct __uintr_frame *frame, uword_t uirrv) { }