Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/x86/um/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  ptrace.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0

#include <linux/sched.h>
#include <linux/elf.h>
#include <linux/regset.h>
#include <asm/user32.h>
#include <asm/sigcontext.h>

#ifdef CONFIG_X86_32
/*
 * FPU tag word conversions.
 */


static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
{
 unsigned int tmp; /* to avoid 16 bit prefixes in the code */

 /* Transform each pair of bits into 01 (valid) or 00 (empty) */
 tmp = ~twd;
 tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
 /* and move the valid bits to the lower byte. */
 tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
 tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
 tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
 return tmp;
}

static inline unsigned long
twd_fxsr_to_i387(const struct user_fxsr_struct *fxsave)
{
 struct _fpxreg *st = NULL;
 unsigned long twd = (unsigned long) fxsave->twd;
 unsigned long tag;
 unsigned long ret = 0xffff0000;
 int i;

#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)

 for (i = 0; i < 8; i++) {
  if (twd & 0x1) {
   st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);

   switch (st->exponent & 0x7fff) {
   case 0x7fff:
    tag = 2;  /* Special */
    break;
   case 0x0000:
    if (!st->significand[0] &&
        !st->significand[1] &&
        !st->significand[2] &&
        !st->significand[3]) {
     tag = 1; /* Zero */
    } else {
     tag = 2; /* Special */
    }
    break;
   default:
    if (st->significand[3] & 0x8000)
     tag = 0; /* Valid */
    else
     tag = 2; /* Special */
    break;
   }
  } else {
   tag = 3;   /* Empty */
  }
  ret |= (tag << (2 * i));
  twd = twd >> 1;
 }
 return ret;
}

/*
 * Get/set the old 32bit i387 registers (pre-FPX)
 *
 * We provide simple wrappers for mcontext.c, they are only defined locally
 * because mcontext.c is userspace facing and needs to a different definition
 * of the structures.
 */

static int _um_i387_from_fxsr(struct membuf to,
         const struct user_fxsr_struct *fxsave)
{
 int i;

 membuf_store(&to, (unsigned long)fxsave->cwd | 0xffff0000ul);
 membuf_store(&to, (unsigned long)fxsave->swd | 0xffff0000ul);
 membuf_store(&to, twd_fxsr_to_i387(fxsave));
 membuf_store(&to, fxsave->fip);
 membuf_store(&to, fxsave->fcs | ((unsigned long)fxsave->fop << 16));
 membuf_store(&to, fxsave->foo);
 membuf_store(&to, fxsave->fos);

 for (i = 0; i < 8; i++)
  membuf_write(&to, (void *)fxsave->st_space + i * 16, 10);

 return 0;
}

int um_i387_from_fxsr(struct user_i387_struct *i387,
        const struct user_fxsr_struct *fxsave);

int um_i387_from_fxsr(struct user_i387_struct *i387,
        const struct user_fxsr_struct *fxsave)
{
 struct membuf to = {
  .p = i387,
  .left = sizeof(*i387),
 };

 return _um_i387_from_fxsr(to, fxsave);
}

static int fpregs_legacy_get(struct task_struct *target,
        const struct user_regset *regset,
        struct membuf to)
{
 struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;

 return _um_i387_from_fxsr(to, fxsave);
}

int um_fxsr_from_i387(struct user_fxsr_struct *fxsave,
        const struct user_i387_struct *from);

int um_fxsr_from_i387(struct user_fxsr_struct *fxsave,
        const struct user_i387_struct *from)
{
 int i;

 fxsave->cwd = (unsigned short)(from->cwd & 0xffff);
 fxsave->swd = (unsigned short)(from->swd & 0xffff);
 fxsave->twd = twd_i387_to_fxsr((unsigned short)(from->twd & 0xffff));
 fxsave->fip = from->fip;
 fxsave->fop = (unsigned short)((from->fcs & 0xffff0000ul) >> 16);
 fxsave->fcs = (from->fcs & 0xffff);
 fxsave->foo = from->foo;
 fxsave->fos = from->fos;

 for (i = 0; i < 8; i++) {
  memcpy((void *)fxsave->st_space + i * 16,
         (void *)from->st_space + i * 10, 10);
 }

 return 0;
}

static int fpregs_legacy_set(struct task_struct *target,
        const struct user_regset *regset,
        unsigned int pos, unsigned int count,
        const void *kbuf, const void __user *ubuf)
{
 struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;
 const struct user_i387_struct *from;
 struct user_i387_struct buf;

 if (ubuf) {
  if (copy_from_user(&buf, ubuf, sizeof(buf)))
   return -EFAULT;
  from = &buf;
 } else {
  from = kbuf;
 }

 return um_fxsr_from_i387(fxsave, from);
}
#endif

static int genregs_get(struct task_struct *target,
         const struct user_regset *regset,
         struct membuf to)
{
 int reg;

 for (reg = 0; to.left; reg++)
  membuf_store(&to, getreg(target, reg * sizeof(unsigned long)));
 return 0;
}

static int genregs_set(struct task_struct *target,
         const struct user_regset *regset,
         unsigned int pos, unsigned int count,
         const void *kbuf, const void __user *ubuf)
{
 int ret = 0;

 if (kbuf) {
  const unsigned long *k = kbuf;

  while (count >= sizeof(*k) && !ret) {
   ret = putreg(target, pos, *k++);
   count -= sizeof(*k);
   pos += sizeof(*k);
  }
 } else {
  const unsigned long  __user *u = ubuf;

  while (count >= sizeof(*u) && !ret) {
   unsigned long word;

   ret = __get_user(word, u++);
   if (ret)
    break;
   ret = putreg(target, pos, word);
   count -= sizeof(*u);
   pos += sizeof(*u);
  }
 }
 return ret;
}

static int generic_fpregs_active(struct task_struct *target, const struct user_regset *regset)
{
 return regset->n;
}

static int generic_fpregs_get(struct task_struct *target,
         const struct user_regset *regset,
         struct membuf to)
{
 void *fpregs = task_pt_regs(target)->regs.fp;

 membuf_write(&to, fpregs, regset->size * regset->n);
 return 0;
}

static int generic_fpregs_set(struct task_struct *target,
         const struct user_regset *regset,
         unsigned int pos, unsigned int count,
         const void *kbuf, const void __user *ubuf)
{
 void *fpregs = task_pt_regs(target)->regs.fp;

 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
      fpregs, 0, regset->size * regset->n);
}

static struct user_regset uml_regsets[] __ro_after_init = {
 [REGSET_GENERAL] = {
  USER_REGSET_NOTE_TYPE(PRSTATUS),
  .n  = sizeof(struct user_regs_struct) / sizeof(long),
  .size  = sizeof(long),
  .align  = sizeof(long),
  .regset_get = genregs_get,
  .set  = genregs_set
 },
#ifdef CONFIG_X86_32
 /* Old FP registers, they are needed in signal frames */
 [REGSET_FP_LEGACY] = {
  USER_REGSET_NOTE_TYPE(PRFPREG),
  .n  = sizeof(struct user_i387_ia32_struct) / sizeof(long),
  .size  = sizeof(long),
  .align  = sizeof(long),
  .active  = generic_fpregs_active,
  .regset_get = fpregs_legacy_get,
  .set  = fpregs_legacy_set,
 },
#endif
 [REGSET_FP] = {
#ifdef CONFIG_X86_32
  USER_REGSET_NOTE_TYPE(PRXFPREG),
  .n  = sizeof(struct user32_fxsr_struct) / sizeof(long),
#else
  USER_REGSET_NOTE_TYPE(PRFPREG),
  .n  = sizeof(struct user_i387_struct) / sizeof(long),
#endif
  .size  = sizeof(long),
  .align  = sizeof(long),
  .active  = generic_fpregs_active,
  .regset_get = generic_fpregs_get,
  .set  = generic_fpregs_set,
 },
 [REGSET_XSTATE] = {
  USER_REGSET_NOTE_TYPE(X86_XSTATE),
  .size  = sizeof(long),
  .align  = sizeof(long),
  .active  = generic_fpregs_active,
  .regset_get = generic_fpregs_get,
  .set  = generic_fpregs_set,
 },
 /* TODO: Add TLS regset for 32bit */
};

static const struct user_regset_view user_uml_view = {
#ifdef CONFIG_X86_32
 .name = "i386", .e_machine = EM_386,
#else
 .name = "x86_64", .e_machine = EM_X86_64,
#endif
 .regsets = uml_regsets, .n = ARRAY_SIZE(uml_regsets)
};

const struct user_regset_view *
task_user_regset_view(struct task_struct *tsk)
{
 return &user_uml_view;
}

static int __init init_regset_xstate_info(void)
{
 uml_regsets[REGSET_XSTATE].n =
  host_fp_size / uml_regsets[REGSET_XSTATE].size;

 return 0;
}
arch_initcall(init_regset_xstate_info);

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.