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

Quelle  extable.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0

#include <linux/bitfield.h>
#include <linux/extable.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/panic.h>
#include <asm/asm-extable.h>
#include <asm/extable.h>
#include <asm/fpu.h>

const struct exception_table_entry *s390_search_extables(unsigned long addr)
{
 const struct exception_table_entry *fixup;
 size_t num;

 fixup = search_exception_tables(addr);
 if (fixup)
  return fixup;
 num = __stop_amode31_ex_table - __start_amode31_ex_table;
 return search_extable(__start_amode31_ex_table, num, addr);
}

static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_regs *regs)
{
 regs->psw.addr = extable_fixup(ex);
 return true;
}

static bool ex_handler_ua_fault(const struct exception_table_entry *ex, struct pt_regs *regs)
{
 unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);

 regs->gprs[reg_err] = -EFAULT;
 regs->psw.addr = extable_fixup(ex);
 return true;
}

static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,
       bool pair, struct pt_regs *regs)
{
 unsigned int reg_zero = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
 unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);

 regs->gprs[reg_err] = -EFAULT;
 regs->gprs[reg_zero] = 0;
 if (pair)
  regs->gprs[reg_zero + 1] = 0;
 regs->psw.addr = extable_fixup(ex);
 return true;
}

static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)
{
 unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
 unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data);
 unsigned long data, addr, offset;

 addr = regs->gprs[reg_addr];
 offset = addr & (sizeof(unsigned long) - 1);
 addr &= ~(sizeof(unsigned long) - 1);
 data = *(unsigned long *)addr;
 data <<= BITS_PER_BYTE * offset;
 regs->gprs[reg_data] = data;
 regs->psw.addr = extable_fixup(ex);
 return true;
}

static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_regs *regs)
{
 fpu_sfpc(0);
 regs->psw.addr = extable_fixup(ex);
 return true;
}

struct insn_ssf {
 u64 opc1 : 8;
 u64 r3   : 4;
 u64 opc2 : 4;
 u64 b1   : 4;
 u64 d1   : 12;
 u64 b2   : 4;
 u64 d2   : 12;
} __packed;

static bool ex_handler_ua_mvcos(const struct exception_table_entry *ex,
    bool from, struct pt_regs *regs)
{
 unsigned long uaddr, remainder;
 struct insn_ssf *insn;

 /*
 * If the faulting user space access crossed a page boundary retry by
 * limiting the access to the first page (adjust length accordingly).
 * Then the mvcos instruction will either complete with condition code
 * zero, or generate another fault where the user space access did not
 * cross a page boundary.
 * If the faulting user space access did not cross a page boundary set
 * length to zero and retry. In this case no user space access will
 * happen, and the mvcos instruction will complete with condition code
 * zero.
 * In both cases the instruction will complete with condition code
 * zero (copying finished), and the register which contains the
 * length, indicates the number of bytes copied.
 */

 regs->psw.addr = extable_fixup(ex);
 insn = (struct insn_ssf *)regs->psw.addr;
 if (from)
  uaddr = regs->gprs[insn->b2] + insn->d2;
 else
  uaddr = regs->gprs[insn->b1] + insn->d1;
 remainder = PAGE_SIZE - (uaddr & (PAGE_SIZE - 1));
 if (regs->gprs[insn->r3] <= remainder)
  remainder = 0;
 regs->gprs[insn->r3] = remainder;
 return true;
}

bool fixup_exception(struct pt_regs *regs)
{
 const struct exception_table_entry *ex;

 ex = s390_search_extables(instruction_pointer(regs));
 if (!ex)
  return false;
 switch (ex->type) {
 case EX_TYPE_FIXUP:
  return ex_handler_fixup(ex, regs);
 case EX_TYPE_BPF:
  return ex_handler_bpf(ex, regs);
 case EX_TYPE_UA_FAULT:
  return ex_handler_ua_fault(ex, regs);
 case EX_TYPE_UA_LOAD_REG:
  return ex_handler_ua_load_reg(ex, false, regs);
 case EX_TYPE_UA_LOAD_REGPAIR:
  return ex_handler_ua_load_reg(ex, true, regs);
 case EX_TYPE_ZEROPAD:
  return ex_handler_zeropad(ex, regs);
 case EX_TYPE_FPC:
  return ex_handler_fpc(ex, regs);
 case EX_TYPE_UA_MVCOS_TO:
  return ex_handler_ua_mvcos(ex, false, regs);
 case EX_TYPE_UA_MVCOS_FROM:
  return ex_handler_ua_mvcos(ex, true, regs);
 }
 panic("invalid exception table entry");
}

Messung V0.5
C=95 H=91 G=92

¤ Dauer der Verarbeitung: 0.12 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.