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

Quelle  alignment.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/ptrace.h>

static int align_kern_enable = 1;
static int align_usr_enable = 1;
static int align_kern_count = 0;
static int align_usr_count = 0;

static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
{
 return rx == 15 ? regs->lr : *((uint32_t *)&(regs->a0) - 2 + rx);
}

static inline void put_ptreg(struct pt_regs *regs, uint32_t rx, uint32_t val)
{
 if (rx == 15)
  regs->lr = val;
 else
  *((uint32_t *)&(regs->a0) - 2 + rx) = val;
}

/*
 * Get byte-value from addr and set it to *valp.
 *
 * Success: return 0
 * Failure: return 1
 */

static int ldb_asm(uint32_t addr, uint32_t *valp)
{
 uint32_t val;
 int err;

 asm volatile (
  "movi %0, 0\n"
  "1:\n"
  "ldb %1, (%2)\n"
  "br 3f\n"
  "2:\n"
  "movi %0, 1\n"
  "br 3f\n"
  ".section __ex_table,\"a\"\n"
  ".align 2\n"
  ".long 1b, 2b\n"
  ".previous\n"
  "3:\n"
  : "=&r"(err), "=r"(val)
  : "r" (addr)
 );

 *valp = val;

 return err;
}

/*
 * Put byte-value to addr.
 *
 * Success: return 0
 * Failure: return 1
 */

static int stb_asm(uint32_t addr, uint32_t val)
{
 int err;

 asm volatile (
  "movi %0, 0\n"
  "1:\n"
  "stb %1, (%2)\n"
  "br 3f\n"
  "2:\n"
  "movi %0, 1\n"
  "br 3f\n"
  ".section __ex_table,\"a\"\n"
  ".align 2\n"
  ".long 1b, 2b\n"
  ".previous\n"
  "3:\n"
  : "=&r"(err)
  : "r"(val), "r" (addr)
 );

 return err;
}

/*
 * Get half-word from [rx + imm]
 *
 * Success: return 0
 * Failure: return 1
 */

static int ldh_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
{
 uint32_t byte0, byte1;

 if (ldb_asm(addr, &byte0))
  return 1;
 addr += 1;
 if (ldb_asm(addr, &byte1))
  return 1;

 byte0 |= byte1 << 8;
 put_ptreg(regs, rz, byte0);

 return 0;
}

/*
 * Store half-word to [rx + imm]
 *
 * Success: return 0
 * Failure: return 1
 */

static int sth_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
{
 uint32_t byte0, byte1;

 byte0 = byte1 = get_ptreg(regs, rz);

 byte0 &= 0xff;

 if (stb_asm(addr, byte0))
  return 1;

 addr += 1;
 byte1 = (byte1 >> 8) & 0xff;
 if (stb_asm(addr, byte1))
  return 1;

 return 0;
}

/*
 * Get word from [rx + imm]
 *
 * Success: return 0
 * Failure: return 1
 */

static int ldw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
{
 uint32_t byte0, byte1, byte2, byte3;

 if (ldb_asm(addr, &byte0))
  return 1;

 addr += 1;
 if (ldb_asm(addr, &byte1))
  return 1;

 addr += 1;
 if (ldb_asm(addr, &byte2))
  return 1;

 addr += 1;
 if (ldb_asm(addr, &byte3))
  return 1;

 byte0 |= byte1 << 8;
 byte0 |= byte2 << 16;
 byte0 |= byte3 << 24;

 put_ptreg(regs, rz, byte0);

 return 0;
}

/*
 * Store word to [rx + imm]
 *
 * Success: return 0
 * Failure: return 1
 */

static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
{
 uint32_t byte0, byte1, byte2, byte3;

 byte0 = byte1 = byte2 = byte3 = get_ptreg(regs, rz);

 byte0 &= 0xff;

 if (stb_asm(addr, byte0))
  return 1;

 addr += 1;
 byte1 = (byte1 >> 8) & 0xff;
 if (stb_asm(addr, byte1))
  return 1;

 addr += 1;
 byte2 = (byte2 >> 16) & 0xff;
 if (stb_asm(addr, byte2))
  return 1;

 addr += 1;
 byte3 = (byte3 >> 24) & 0xff;
 if (stb_asm(addr, byte3))
  return 1;

 return 0;
}

extern int fixup_exception(struct pt_regs *regs);

#define OP_LDH 0xc000
#define OP_STH 0xd000
#define OP_LDW 0x8000
#define OP_STW 0x9000

void csky_alignment(struct pt_regs *regs)
{
 int ret;
 uint16_t tmp;
 uint32_t opcode = 0;
 uint32_t rx     = 0;
 uint32_t rz     = 0;
 uint32_t imm    = 0;
 uint32_t addr   = 0;

 if (!user_mode(regs))
  goto kernel_area;

 if (!align_usr_enable) {
  pr_err("%s user disabled.\n", __func__);
  goto bad_area;
 }

 align_usr_count++;

 ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
 if (ret) {
  pr_err("%s get_user failed.\n", __func__);
  goto bad_area;
 }

 goto good_area;

kernel_area:
 if (!align_kern_enable) {
  pr_err("%s kernel disabled.\n", __func__);
  goto bad_area;
 }

 align_kern_count++;

 tmp = *(uint16_t *)instruction_pointer(regs);

good_area:
 opcode = (uint32_t)tmp;

 rx  = opcode & 0xf;
 imm = (opcode >> 4) & 0xf;
 rz  = (opcode >> 8) & 0xf;
 opcode &= 0xf000;

 if (rx == 0 || rx == 1 || rz == 0 || rz == 1)
  goto bad_area;

 switch (opcode) {
 case OP_LDH:
  addr = get_ptreg(regs, rx) + (imm << 1);
  ret = ldh_c(regs, rz, addr);
  break;
 case OP_LDW:
  addr = get_ptreg(regs, rx) + (imm << 2);
  ret = ldw_c(regs, rz, addr);
  break;
 case OP_STH:
  addr = get_ptreg(regs, rx) + (imm << 1);
  ret = sth_c(regs, rz, addr);
  break;
 case OP_STW:
  addr = get_ptreg(regs, rx) + (imm << 2);
  ret = stw_c(regs, rz, addr);
  break;
 }

 if (ret)
  goto bad_area;

 regs->pc += 2;

 return;

bad_area:
 if (!user_mode(regs)) {
  if (fixup_exception(regs))
   return;

  bust_spinlocks(1);
  pr_alert("%s opcode: %x, rz: %d, rx: %d, imm: %d, addr: %x.\n",
    __func__, opcode, rz, rx, imm, addr);
  show_regs(regs);
  bust_spinlocks(0);
  make_task_dead(SIGKILL);
 }

 force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
}

static const struct ctl_table alignment_tbl[] = {
 {
  .procname = "kernel_enable",
  .data = &align_kern_enable,
  .maxlen = sizeof(align_kern_enable),
  .mode = 0666,
  .proc_handler = &proc_dointvec
 },
 {
  .procname = "user_enable",
  .data = &align_usr_enable,
  .maxlen = sizeof(align_usr_enable),
  .mode = 0666,
  .proc_handler = &proc_dointvec
 },
 {
  .procname = "kernel_count",
  .data = &align_kern_count,
  .maxlen = sizeof(align_kern_count),
  .mode = 0666,
  .proc_handler = &proc_dointvec
 },
 {
  .procname = "user_count",
  .data = &align_usr_count,
  .maxlen = sizeof(align_usr_count),
  .mode = 0666,
  .proc_handler = &proc_dointvec
 },
};

static int __init csky_alignment_init(void)
{
 register_sysctl_init("csky/csky_alignment", alignment_tbl);
 return 0;
}

arch_initcall(csky_alignment_init);

Messung V0.5
C=98 H=91 G=94

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