From 078c7498908d9b74caff34d12099b5c85470e277 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 9 Dec 2020 18:14:24 -0800 Subject: [PATCH] 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. --- gcc/config/i386/uintrintrin.h | 3 -- gcc/testsuite/gcc.dg/guality/pr98219-1.c | 49 ++++++++++++++++++ gcc/testsuite/gcc.dg/guality/pr98219-2.c | 63 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr98219-1.c | 45 +++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr98219-2.c | 59 ++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/uintr-2.c | 7 ++- gcc/testsuite/gcc.target/i386/uintr-3.c | 6 ++- gcc/testsuite/gcc.target/i386/uintr-4.c | 6 ++- gcc/testsuite/gcc.target/i386/uintr-5.c | 4 +- 9 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/guality/pr98219-1.c create mode 100644 gcc/testsuite/gcc.dg/guality/pr98219-2.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr98219-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr98219-2.c diff --git a/gcc/config/i386/uintrintrin.h b/gcc/config/i386/uintrintrin.h index 991f6427971..4606caf8582 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 00000000000..c9cb8a51b34 --- /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 00000000000..1f74eb3a82c --- /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 00000000000..89b5aa3b9cb --- /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 00000000000..c2f33f84f3e --- /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 e705732c1bd..0a83c662b94 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 d2843495158..92476cfa45c 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 f3b371b4231..4d0ec34dfa0 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 ac44be0a706..49cb2ec8097 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) { } -- 2.30.2