mbox series

[v1,0/6] linux-user/loongarch64: Add LSX/LASX sigcontext

Message ID 20231010033701.385725-1-gaosong@loongson.cn (mailing list archive)
Headers show
Series linux-user/loongarch64: Add LSX/LASX sigcontext | expand

Message

Song Gao Oct. 10, 2023, 3:36 a.m. UTC
Hi, All.

This series adds save/restore sigcontext. 

We use extctx_flags to choces which sigcontext need save/restore.

The extctx_flags default value is EXTCTX_FLAGS_FPU, we need
save/restore fpu context.

After a LSX/LASX instruction is execed, extctx_flags value change to
EXTCTX_FLAGS_LSX/LASX, we always need save/restore lsx/lasx context.


The test_signal.c is a simple test.

The default vreg len is 64. After execed a LSX instruction, the vreg len is 
128, and then we exec a FPU instruction, the vreg len is also 128. After
execed a LASX instruction, the vreg len is 256, and then we exec a FPU
instruction, the vreg len is also 256.

test_signal.c:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <asm/ucontext.h>
#include <setjmp.h>
#include <stdint.h>
#include <string.h>

static sigjmp_buf jmpbuf;

struct _ctx_layout {
        struct sctx_info *addr;
        unsigned int size;
};

struct extctx_layout {
        unsigned long size;
        unsigned int flags;
        struct _ctx_layout fpu;
        struct _ctx_layout lsx;
        struct _ctx_layout lasx;
        struct _ctx_layout end;
};
static int parse_extcontext(struct sigcontext *sc, struct extctx_layout *extctx)
{
    uint32_t magic, size;
    struct sctx_info *info = (struct sctx_info *)&sc->sc_extcontext;

    while(1) {
        magic = (uint32_t)info->magic;
        size =  (uint32_t)info->size;

        printf("magic is %lx\n", magic);
        printf("size is %lx\n", size);
        switch (magic) {
        case 0: /* END*/
            return 0;
        case FPU_CTX_MAGIC:
            if (size < (sizeof(struct sctx_info) +
                        sizeof(struct fpu_context))) {
                return -1;
            }
            extctx->fpu.addr = info;
            break;
        case LSX_CTX_MAGIC:
            if (size < (sizeof(struct sctx_info) +
                        sizeof(struct lsx_context))) {
                return -1;
            }
            extctx->lsx.addr = info;
            break;
        case LASX_CTX_MAGIC:
            if (size < (sizeof(struct sctx_info) +
                        sizeof(struct lasx_context))) {
                return -1;
            }
            extctx->lasx.addr = info;
            break;
        default:
            return -1;
        }
        info = (struct sctx_info *)((char *)info +size);
    }
    return 0;
}

static int n = 0;

static void do_signal(int sig, siginfo_t *info, void *ucontext)
{
    int i;
    struct ucontext *uc = (struct ucontext *)ucontext;
    struct extctx_layout extctx;

    memset(&extctx, 0, sizeof(struct extctx_layout));

    printf("pc        : %016lx\n", uc->uc_mcontext.sc_pc);

    parse_extcontext(&uc->uc_mcontext, &extctx);

    if (n < 5) {
        printf("extctx.lasx.addr is %lx\n", extctx.lasx.addr);
        printf("extctx.lsx.addr  is %lx\n", extctx.lsx.addr);
        printf("extctx.fpu.addr  is %lx\n", extctx.fpu.addr);

        if (extctx.lasx.addr) {
            struct sctx_info *info = extctx.lasx.addr;
            struct lasx_context *lasx_ctx = (struct lasx_context *)((char *)info +
                                            sizeof(struct sctx_info));
            printf("vl        : %016lx\n", 256);
        } else if (extctx.lsx.addr) {
            struct sctx_info *info = extctx.lsx.addr;
            struct lsx_context *lsx_ctx = (struct lsx_context *)((char *)info +
                                          sizeof(struct sctx_info));
            printf("vl        : %016lx\n", 128);
        } else if (extctx.fpu.addr) {
            struct sctx_info *info = extctx.fpu.addr;
            struct fpu_context *fpu_ctx = (struct fpu_context *)((char *)info +
                                          sizeof(struct sctx_info));
            printf("vl        : %016lx\n", 64);
        }
    }
    n++;

    printf("n is -------------- %d\n", n);
    if (n == 1) {
        // vaddwev.w.hu    $vr27, $vr22, $vr29
        asm volatile(".word 0x702ef6db");
        printf("After execed LSX instructons  vaddwev.w.hu\n");
    }

    if (n == 2) {
        // 0101395e        fadd.d          $fs6, $ft2, $ft6
        asm volatile(".word 0x0101395e");
        printf("After execed FPU instructions fadd\n");
    }

    if (n == 3) {
        // xvextrins.d     $xr13, $xr15, 0x59
        asm volatile(".word 0x778165ed");
        printf("After execed LASX instructions xvextrins.d\n");
    }

    if (n == 4) {
        // 0101395e        fadd.d          $fs6, $ft2, $ft6
        asm volatile(".word 0x0101395e");
        printf("After execed FPU instructions fadd\n");
    }

    if (n == 5) {
        exit(0);
    }

    siglongjmp(jmpbuf, 1);
}

static int setup_signal(int sig, void (*fn) (int, siginfo_t *, void *))
{
    struct sigaction my_act;
    int ret;

    my_act.sa_sigaction = fn;
    my_act.sa_flags = SA_SIGINFO;
    sigemptyset(&my_act.sa_mask);

    ret = sigaction(sig, &my_act, NULL);
    if (ret != 0) {
        printf("FAIL: signal %d\n", sig);
        return SIG_ERR;
    }
}

int main()
{
    setup_signal(SIGSEGV, do_signal);

    sigsetjmp(jmpbuf, 1);

    int result = 0;
    void *addr = 0x00012;
    result = *(int *)addr;

    return 0;
}


On 3A5000 machine:

[root@archlinux LASX]# ./test_signal 
pc        : 0000000120000b44
magic is 46505501
size is 120
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 0
extctx.fpu.addr  is 7ffffbdd2120
vl        : 0000000000000040
n is -------------- 1
After execed LSX instructons  vaddwev.w.hu
pc        : 0000000120000b44
magic is 53580001
size is 220
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 7ffffbdd2020
extctx.fpu.addr  is 0
vl        : 0000000000000080
n is -------------- 2
After execed FPU instructions fadd
pc        : 0000000120000b44
magic is 53580001
size is 220
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 7ffffbdd2020
extctx.fpu.addr  is 0
vl        : 0000000000000080
n is -------------- 3
After execed LASX instructions xvextrins.d
pc        : 0000000120000b44
magic is 41535801
size is 430
magic is 0
size is 0
extctx.lasx.addr is 7ffffbdd1e10
extctx.lsx.addr  is 0
extctx.fpu.addr  is 0
vl        : 0000000000000100
n is -------------- 4
After execed FPU instructions fadd
pc        : 0000000120000b44
magic is 41535801
size is 430
magic is 0
size is 0
extctx.lasx.addr is 7ffffbdd1e10
extctx.lsx.addr  is 0
extctx.fpu.addr  is 0
vl        : 0000000000000100
n is -------------- 5

QEMU user-mode on X86:

root@loongson-KVM:~/work/code/qemu# ./build/qemu-loongarch64 test_signal
pc        : 0000000120000b44
magic is 46505501
size is 120
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 0
extctx.fpu.addr  is 7fd92279f110
vl        : 0000000000000040
n is -------------- 1
After exec LSX instructons  vaddwev.w.hu
pc        : 0000000120000b44
magic is 53580001
size is 220
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 7fd92279f010
extctx.fpu.addr  is 0
vl        : 0000000000000080
n is -------------- 2
After execed FPU instructions fadd
pc        : 0000000120000b44
magic is 53580001
size is 220
magic is 0
size is 0
extctx.lasx.addr is 0
extctx.lsx.addr  is 7fd92279f010
extctx.fpu.addr  is 0
vl        : 0000000000000080
n is -------------- 3
After execed LASX instructions xvextrins.d
pc        : 0000000120000b44
magic is 41535801
size is 430
magic is 0
size is 0
extctx.lasx.addr is 7fd92279ee00
extctx.lsx.addr  is 0
extctx.fpu.addr  is 0
vl        : 0000000000000100
n is -------------- 4
After execed FPU instructions fadd
pc        : 0000000120000b44
magic is 41535801
size is 430
magic is 0
size is 0
extctx.lasx.addr is 7fd92279ee00
extctx.lsx.addr  is 0
extctx.fpu.addr  is 0
vl        : 0000000000000100
n is -------------- 5


Please review, thanks.

Song Gao (6):
  target/loongarch: Add env->extctx_flags for user-mode setup extcontext
  target/loongarch: Add set_vec_extctx to set LSX/LASX instructions
    extctx_flags
  linux-user/loongarch64: Fix setup_extcontext alloc wrong fpu_context
    size
  linux-user/loongarch64: setup_sigframe() set 'end' context size 0
  linux-user/loongarch64: Add LSX sigcontext save/restore
  linux-user/loongarch64: Add LASX sigcontext save/restore

 linux-user/loongarch64/signal.c             | 168 +++++++++++++++++---
 target/loongarch/cpu.c                      |   2 +
 target/loongarch/cpu.h                      |   2 +
 target/loongarch/insn_trans/trans_vec.c.inc |  12 ++
 target/loongarch/internals.h                |   4 +
 target/loongarch/translate.c                |   3 +
 target/loongarch/translate.h                |   1 +
 7 files changed, 170 insertions(+), 22 deletions(-)

Comments

Song Gao Oct. 23, 2023, 2:47 a.m. UTC | #1
Ping !

在 2023/10/10 上午11:36, Song Gao 写道:
> Hi, All.
>
> This series adds save/restore sigcontext.
>
> We use extctx_flags to choces which sigcontext need save/restore.
>
> The extctx_flags default value is EXTCTX_FLAGS_FPU, we need
> save/restore fpu context.
>
> After a LSX/LASX instruction is execed, extctx_flags value change to
> EXTCTX_FLAGS_LSX/LASX, we always need save/restore lsx/lasx context.
>
>
> The test_signal.c is a simple test.
>
> The default vreg len is 64. After execed a LSX instruction, the vreg len is
> 128, and then we exec a FPU instruction, the vreg len is also 128. After
> execed a LASX instruction, the vreg len is 256, and then we exec a FPU
> instruction, the vreg len is also 256.
>
> test_signal.c:
>
> #include <unistd.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <errno.h>
> #include <signal.h>
> #include <asm/ucontext.h>
> #include <setjmp.h>
> #include <stdint.h>
> #include <string.h>
>
> static sigjmp_buf jmpbuf;
>
> struct _ctx_layout {
>          struct sctx_info *addr;
>          unsigned int size;
> };
>
> struct extctx_layout {
>          unsigned long size;
>          unsigned int flags;
>          struct _ctx_layout fpu;
>          struct _ctx_layout lsx;
>          struct _ctx_layout lasx;
>          struct _ctx_layout end;
> };
> static int parse_extcontext(struct sigcontext *sc, struct extctx_layout *extctx)
> {
>      uint32_t magic, size;
>      struct sctx_info *info = (struct sctx_info *)&sc->sc_extcontext;
>
>      while(1) {
>          magic = (uint32_t)info->magic;
>          size =  (uint32_t)info->size;
>
>          printf("magic is %lx\n", magic);
>          printf("size is %lx\n", size);
>          switch (magic) {
>          case 0: /* END*/
>              return 0;
>          case FPU_CTX_MAGIC:
>              if (size < (sizeof(struct sctx_info) +
>                          sizeof(struct fpu_context))) {
>                  return -1;
>              }
>              extctx->fpu.addr = info;
>              break;
>          case LSX_CTX_MAGIC:
>              if (size < (sizeof(struct sctx_info) +
>                          sizeof(struct lsx_context))) {
>                  return -1;
>              }
>              extctx->lsx.addr = info;
>              break;
>          case LASX_CTX_MAGIC:
>              if (size < (sizeof(struct sctx_info) +
>                          sizeof(struct lasx_context))) {
>                  return -1;
>              }
>              extctx->lasx.addr = info;
>              break;
>          default:
>              return -1;
>          }
>          info = (struct sctx_info *)((char *)info +size);
>      }
>      return 0;
> }
>
> static int n = 0;
>
> static void do_signal(int sig, siginfo_t *info, void *ucontext)
> {
>      int i;
>      struct ucontext *uc = (struct ucontext *)ucontext;
>      struct extctx_layout extctx;
>
>      memset(&extctx, 0, sizeof(struct extctx_layout));
>
>      printf("pc        : %016lx\n", uc->uc_mcontext.sc_pc);
>
>      parse_extcontext(&uc->uc_mcontext, &extctx);
>
>      if (n < 5) {
>          printf("extctx.lasx.addr is %lx\n", extctx.lasx.addr);
>          printf("extctx.lsx.addr  is %lx\n", extctx.lsx.addr);
>          printf("extctx.fpu.addr  is %lx\n", extctx.fpu.addr);
>
>          if (extctx.lasx.addr) {
>              struct sctx_info *info = extctx.lasx.addr;
>              struct lasx_context *lasx_ctx = (struct lasx_context *)((char *)info +
>                                              sizeof(struct sctx_info));
>              printf("vl        : %016lx\n", 256);
>          } else if (extctx.lsx.addr) {
>              struct sctx_info *info = extctx.lsx.addr;
>              struct lsx_context *lsx_ctx = (struct lsx_context *)((char *)info +
>                                            sizeof(struct sctx_info));
>              printf("vl        : %016lx\n", 128);
>          } else if (extctx.fpu.addr) {
>              struct sctx_info *info = extctx.fpu.addr;
>              struct fpu_context *fpu_ctx = (struct fpu_context *)((char *)info +
>                                            sizeof(struct sctx_info));
>              printf("vl        : %016lx\n", 64);
>          }
>      }
>      n++;
>
>      printf("n is -------------- %d\n", n);
>      if (n == 1) {
>          // vaddwev.w.hu    $vr27, $vr22, $vr29
>          asm volatile(".word 0x702ef6db");
>          printf("After execed LSX instructons  vaddwev.w.hu\n");
>      }
>
>      if (n == 2) {
>          // 0101395e        fadd.d          $fs6, $ft2, $ft6
>          asm volatile(".word 0x0101395e");
>          printf("After execed FPU instructions fadd\n");
>      }
>
>      if (n == 3) {
>          // xvextrins.d     $xr13, $xr15, 0x59
>          asm volatile(".word 0x778165ed");
>          printf("After execed LASX instructions xvextrins.d\n");
>      }
>
>      if (n == 4) {
>          // 0101395e        fadd.d          $fs6, $ft2, $ft6
>          asm volatile(".word 0x0101395e");
>          printf("After execed FPU instructions fadd\n");
>      }
>
>      if (n == 5) {
>          exit(0);
>      }
>
>      siglongjmp(jmpbuf, 1);
> }
>
> static int setup_signal(int sig, void (*fn) (int, siginfo_t *, void *))
> {
>      struct sigaction my_act;
>      int ret;
>
>      my_act.sa_sigaction = fn;
>      my_act.sa_flags = SA_SIGINFO;
>      sigemptyset(&my_act.sa_mask);
>
>      ret = sigaction(sig, &my_act, NULL);
>      if (ret != 0) {
>          printf("FAIL: signal %d\n", sig);
>          return SIG_ERR;
>      }
> }
>
> int main()
> {
>      setup_signal(SIGSEGV, do_signal);
>
>      sigsetjmp(jmpbuf, 1);
>
>      int result = 0;
>      void *addr = 0x00012;
>      result = *(int *)addr;
>
>      return 0;
> }
>
>
> On 3A5000 machine:
>
> [root@archlinux LASX]# ./test_signal
> pc        : 0000000120000b44
> magic is 46505501
> size is 120
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 7ffffbdd2120
> vl        : 0000000000000040
> n is -------------- 1
> After execed LSX instructons  vaddwev.w.hu
> pc        : 0000000120000b44
> magic is 53580001
> size is 220
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 7ffffbdd2020
> extctx.fpu.addr  is 0
> vl        : 0000000000000080
> n is -------------- 2
> After execed FPU instructions fadd
> pc        : 0000000120000b44
> magic is 53580001
> size is 220
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 7ffffbdd2020
> extctx.fpu.addr  is 0
> vl        : 0000000000000080
> n is -------------- 3
> After execed LASX instructions xvextrins.d
> pc        : 0000000120000b44
> magic is 41535801
> size is 430
> magic is 0
> size is 0
> extctx.lasx.addr is 7ffffbdd1e10
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 0
> vl        : 0000000000000100
> n is -------------- 4
> After execed FPU instructions fadd
> pc        : 0000000120000b44
> magic is 41535801
> size is 430
> magic is 0
> size is 0
> extctx.lasx.addr is 7ffffbdd1e10
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 0
> vl        : 0000000000000100
> n is -------------- 5
>
> QEMU user-mode on X86:
>
> root@loongson-KVM:~/work/code/qemu# ./build/qemu-loongarch64 test_signal
> pc        : 0000000120000b44
> magic is 46505501
> size is 120
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 7fd92279f110
> vl        : 0000000000000040
> n is -------------- 1
> After exec LSX instructons  vaddwev.w.hu
> pc        : 0000000120000b44
> magic is 53580001
> size is 220
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 7fd92279f010
> extctx.fpu.addr  is 0
> vl        : 0000000000000080
> n is -------------- 2
> After execed FPU instructions fadd
> pc        : 0000000120000b44
> magic is 53580001
> size is 220
> magic is 0
> size is 0
> extctx.lasx.addr is 0
> extctx.lsx.addr  is 7fd92279f010
> extctx.fpu.addr  is 0
> vl        : 0000000000000080
> n is -------------- 3
> After execed LASX instructions xvextrins.d
> pc        : 0000000120000b44
> magic is 41535801
> size is 430
> magic is 0
> size is 0
> extctx.lasx.addr is 7fd92279ee00
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 0
> vl        : 0000000000000100
> n is -------------- 4
> After execed FPU instructions fadd
> pc        : 0000000120000b44
> magic is 41535801
> size is 430
> magic is 0
> size is 0
> extctx.lasx.addr is 7fd92279ee00
> extctx.lsx.addr  is 0
> extctx.fpu.addr  is 0
> vl        : 0000000000000100
> n is -------------- 5
>
>
> Please review, thanks.
>
> Song Gao (6):
>    target/loongarch: Add env->extctx_flags for user-mode setup extcontext
>    target/loongarch: Add set_vec_extctx to set LSX/LASX instructions
>      extctx_flags
>    linux-user/loongarch64: Fix setup_extcontext alloc wrong fpu_context
>      size
>    linux-user/loongarch64: setup_sigframe() set 'end' context size 0
>    linux-user/loongarch64: Add LSX sigcontext save/restore
>    linux-user/loongarch64: Add LASX sigcontext save/restore
>
>   linux-user/loongarch64/signal.c             | 168 +++++++++++++++++---
>   target/loongarch/cpu.c                      |   2 +
>   target/loongarch/cpu.h                      |   2 +
>   target/loongarch/insn_trans/trans_vec.c.inc |  12 ++
>   target/loongarch/internals.h                |   4 +
>   target/loongarch/translate.c                |   3 +
>   target/loongarch/translate.h                |   1 +
>   7 files changed, 170 insertions(+), 22 deletions(-)
>