Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellcode-Bibliothek sys_m68k.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * linux/arch/m68k/kernel/sys_m68k.c
 *
 * This file contains various random system calls that
 * have a non-standard calling sequence on the Linux/m68k
 * platform.
 */


#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/smp.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/syscalls.h>
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/ipc.h>

#include <asm/setup.h>
#include <linux/uaccess.h>
#include <asm/cachectl.h>
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/syscalls.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>

#ifdef CONFIG_MMU

#include <asm/tlb.h>

#include "../mm/fault.h"

asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
 unsigned long prot, unsigned long flags,
 unsigned long fd, unsigned long pgoff)
{
 /*
 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
 * so we need to shift the argument down by 1; m68k mmap64(3)
 * (in libc) expects the last argument of mmap2 in 4Kb units.
 */

 return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
}

/* Convert virtual (user) address VADDR to physical address PADDR */
#define virt_to_phys_040(vaddr)      \
({         \
  unsigned long _mmusr, _paddr;      \
         \
  __asm__ __volatile__ (".chip 68040\n\t"    \
   "ptestr (%1)\n\t"    \
   "movec %%mmusr,%0\n\t"    \
   ".chip 68k"     \
   : "=r" (_mmusr)     \
   : "a" (vaddr));     \
  _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0;  \
  _paddr;        \
})

static inline int
cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
{
  unsigned long paddr, i;

  switch (scope)
    {
    case FLUSH_SCOPE_ALL:
      switch (cache)
 {
 case FLUSH_CACHE_DATA:
   /* This nop is needed for some broken versions of the 68040.  */
   __asm__ __volatile__ ("nop\n\t"
    ".chip 68040\n\t"
    "cpusha %dc\n\t"
    ".chip 68k");
   break;
 case FLUSH_CACHE_INSN:
   __asm__ __volatile__ ("nop\n\t"
    ".chip 68040\n\t"
    "cpusha %ic\n\t"
    ".chip 68k");
   break;
 default:
 case FLUSH_CACHE_BOTH:
   __asm__ __volatile__ ("nop\n\t"
    ".chip 68040\n\t"
    "cpusha %bc\n\t"
    ".chip 68k");
   break;
 }
      break;

    case FLUSH_SCOPE_LINE:
      /* Find the physical address of the first mapped page in the
 address range.  */

      if ((paddr = virt_to_phys_040(addr))) {
        paddr += addr & ~(PAGE_MASK | 15);
        len = (len + (addr & 15) + 15) >> 4;
      } else {
 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);

 if (len <= tmp)
   return 0;
 addr += tmp;
 len -= tmp;
 tmp = PAGE_SIZE;
 for (;;)
   {
     if ((paddr = virt_to_phys_040(addr)))
       break;
     if (len <= tmp)
       return 0;
     addr += tmp;
     len -= tmp;
   }
 len = (len + 15) >> 4;
      }
      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
      while (len--)
 {
   switch (cache)
     {
     case FLUSH_CACHE_DATA:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushl %%dc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     case FLUSH_CACHE_INSN:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushl %%ic,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     default:
     case FLUSH_CACHE_BOTH:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushl %%bc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     }
   if (!--i && len)
     {
       /*
       * No need to page align here since it is done by
       * virt_to_phys_040().
       */

       addr += PAGE_SIZE;
       i = PAGE_SIZE / 16;
       /* Recompute physical address when crossing a page
         boundary. */

       for (;;)
  {
    if ((paddr = virt_to_phys_040(addr)))
      break;
    if (len <= i)
      return 0;
    len -= i;
    addr += PAGE_SIZE;
  }
     }
   else
     paddr += 16;
 }
      break;

    default:
    case FLUSH_SCOPE_PAGE:
      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
 {
   if (!(paddr = virt_to_phys_040(addr)))
     continue;
   switch (cache)
     {
     case FLUSH_CACHE_DATA:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushp %%dc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     case FLUSH_CACHE_INSN:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushp %%ic,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     default:
     case FLUSH_CACHE_BOTH:
       __asm__ __volatile__ ("nop\n\t"
        ".chip 68040\n\t"
        "cpushp %%bc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     }
 }
      break;
    }
  return 0;
}

#define virt_to_phys_060(vaddr)    \
({       \
  unsigned long paddr;     \
  __asm__ __volatile__ (".chip 68060\n\t"  \
   "plpar (%0)\n\t"  \
   ".chip 68k"   \
   : "=a" (paddr)   \
   : "0" (vaddr));   \
  (paddr); /* XXX */ \
})

static inline int
cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
{
  unsigned long paddr, i;

  /*
   * 68060 manual says:
   *  cpush %dc : flush DC, remains valid (with our %cacr setup)
   *  cpush %ic : invalidate IC
   *  cpush %bc : flush DC + invalidate IC
   */

  switch (scope)
    {
    case FLUSH_SCOPE_ALL:
      switch (cache)
 {
 case FLUSH_CACHE_DATA:
   __asm__ __volatile__ (".chip 68060\n\t"
    "cpusha %dc\n\t"
    ".chip 68k");
   break;
 case FLUSH_CACHE_INSN:
   __asm__ __volatile__ (".chip 68060\n\t"
    "cpusha %ic\n\t"
    ".chip 68k");
   break;
 default:
 case FLUSH_CACHE_BOTH:
   __asm__ __volatile__ (".chip 68060\n\t"
    "cpusha %bc\n\t"
    ".chip 68k");
   break;
 }
      break;

    case FLUSH_SCOPE_LINE:
      /* Find the physical address of the first mapped page in the
 address range.  */

      len += addr & 15;
      addr &= -16;
      if (!(paddr = virt_to_phys_060(addr))) {
 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);

 if (len <= tmp)
   return 0;
 addr += tmp;
 len -= tmp;
 tmp = PAGE_SIZE;
 for (;;)
   {
     if ((paddr = virt_to_phys_060(addr)))
       break;
     if (len <= tmp)
       return 0;
     addr += tmp;
     len -= tmp;
   }
      }
      len = (len + 15) >> 4;
      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
      while (len--)
 {
   switch (cache)
     {
     case FLUSH_CACHE_DATA:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushl %%dc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     case FLUSH_CACHE_INSN:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushl %%ic,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     default:
     case FLUSH_CACHE_BOTH:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushl %%bc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     }
   if (!--i && len)
     {

       /*
       * We just want to jump to the first cache line
       * in the next page.
       */

       addr += PAGE_SIZE;
       addr &= PAGE_MASK;

       i = PAGE_SIZE / 16;
       /* Recompute physical address when crossing a page
         boundary. */

       for (;;)
         {
           if ((paddr = virt_to_phys_060(addr)))
             break;
           if (len <= i)
             return 0;
           len -= i;
           addr += PAGE_SIZE;
         }
     }
   else
     paddr += 16;
 }
      break;

    default:
    case FLUSH_SCOPE_PAGE:
      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
      addr &= PAGE_MASK; /* Workaround for bug in some
   revisions of the 68060 */

      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
 {
   if (!(paddr = virt_to_phys_060(addr)))
     continue;
   switch (cache)
     {
     case FLUSH_CACHE_DATA:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushp %%dc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     case FLUSH_CACHE_INSN:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushp %%ic,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     default:
     case FLUSH_CACHE_BOTH:
       __asm__ __volatile__ (".chip 68060\n\t"
        "cpushp %%bc,(%0)\n\t"
        ".chip 68k"
        : : "a" (paddr));
       break;
     }
 }
      break;
    }
  return 0;
}

/* sys_cacheflush -- flush (part of) the processor cache.  */
asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{
 int ret = -EINVAL;

 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
     cache & ~FLUSH_CACHE_BOTH)
  goto out;

 if (scope == FLUSH_SCOPE_ALL) {
  /* Only the superuser may explicitly flush the whole cache. */
  ret = -EPERM;
  if (!capable(CAP_SYS_ADMIN))
   goto out;

  mmap_read_lock(current->mm);
 } else {
  struct vm_area_struct *vma;

  /* Check for overflow.  */
  if (addr + len < addr)
   goto out;

  /*
 * Verify that the specified address region actually belongs
 * to this process.
 */

  mmap_read_lock(current->mm);
  vma = vma_lookup(current->mm, addr);
  if (!vma || addr + len > vma->vm_end)
   goto out_unlock;
 }

 if (CPU_IS_020_OR_030) {
  if (scope == FLUSH_SCOPE_LINE && len < 256) {
   unsigned long cacr;
   __asm__ ("movec %%cacr, %0" : "=r" (cacr));
   if (cache & FLUSH_CACHE_INSN)
    cacr |= 4;
   if (cache & FLUSH_CACHE_DATA)
    cacr |= 0x400;
   len >>= 2;
   while (len--) {
    __asm__ __volatile__ ("movec %1, %%caar\n\t"
            "movec %0, %%cacr"
            : /* no outputs */
            : "r" (cacr), "r" (addr));
    addr += 4;
   }
  } else {
   /* Flush the whole cache, even if page granularity requested. */
   unsigned long cacr;
   __asm__ ("movec %%cacr, %0" : "=r" (cacr));
   if (cache & FLUSH_CACHE_INSN)
    cacr |= 8;
   if (cache & FLUSH_CACHE_DATA)
    cacr |= 0x800;
   __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
  }
  ret = 0;
  goto out_unlock;
 } else {
     /*
     * 040 or 060: don't blindly trust 'scope', someone could
     * try to flush a few megs of memory.
     */


     if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
         scope=FLUSH_SCOPE_PAGE;
     if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
         scope=FLUSH_SCOPE_ALL;
     if (CPU_IS_040) {
  ret = cache_flush_040 (addr, scope, cache, len);
     } else if (CPU_IS_060) {
  ret = cache_flush_060 (addr, scope, cache, len);
     }
 }
out_unlock:
 mmap_read_unlock(current->mm);
out:
 return ret;
}

/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
   D1 (newval).  */

asmlinkage int
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
        unsigned long __user * mem)
{
 /* This was borrowed from ARM's implementation.  */
 for (;;) {
  struct mm_struct *mm = current->mm;
  pgd_t *pgd;
  p4d_t *p4d;
  pud_t *pud;
  pmd_t *pmd;
  pte_t *pte;
  spinlock_t *ptl;
  unsigned long mem_value;

  mmap_read_lock(mm);
  pgd = pgd_offset(mm, (unsigned long)mem);
  if (!pgd_present(*pgd))
   goto bad_access;
  p4d = p4d_offset(pgd, (unsigned long)mem);
  if (!p4d_present(*p4d))
   goto bad_access;
  pud = pud_offset(p4d, (unsigned long)mem);
  if (!pud_present(*pud))
   goto bad_access;
  pmd = pmd_offset(pud, (unsigned long)mem);
  if (!pmd_present(*pmd))
   goto bad_access;
  pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
  if (!pte)
   goto bad_access;
  if (!pte_present(*pte) || !pte_dirty(*pte)
      || !pte_write(*pte)) {
   pte_unmap_unlock(pte, ptl);
   goto bad_access;
  }

  /*
 * No need to check for EFAULT; we know that the page is
 * present and writable.
 */

  __get_user(mem_value, mem);
  if (mem_value == oldval)
   __put_user(newval, mem);

  pte_unmap_unlock(pte, ptl);
  mmap_read_unlock(mm);
  return mem_value;

       bad_access:
  mmap_read_unlock(mm);
  /* This is not necessarily a bad access, we can get here if
   a memory we're trying to write to should be copied-on-write.
   Make the kernel do the necessary page stuff, then re-iterate.
   Simulate a write access fault to do that.  */

  {
   /* The first argument of the function corresponds to
   D1, which is the first field of struct pt_regs.  */

   struct pt_regs *fp = (struct pt_regs *)&newval;

   /* '3' is an RMW flag.  */
   if (do_page_fault(fp, (unsigned long)mem, 3))
    /* If the do_page_fault() failed, we don't
   have anything meaningful to return.
   There should be a SIGSEGV pending for
   the process.  */

    return 0xdeadbeef;
  }
 }
}

#else

/* sys_cacheflush -- flush (part of) the processor cache.  */
asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{
 flush_cache_all();
 return 0;
}

/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
   D1 (newval).  */

asmlinkage int
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
        unsigned long __user * mem)
{
 struct mm_struct *mm = current->mm;
 unsigned long mem_value;

 mmap_read_lock(mm);

 mem_value = *mem;
 if (mem_value == oldval)
  *mem = newval;

 mmap_read_unlock(mm);
 return mem_value;
}

#endif /* CONFIG_MMU */

asmlinkage int sys_getpagesize(void)
{
 return PAGE_SIZE;
}

asmlinkage unsigned long sys_get_thread_area(void)
{
 return current_thread_info()->tp_value;
}

asmlinkage int sys_set_thread_area(unsigned long tp)
{
 current_thread_info()->tp_value = tp;
 return 0;
}

asmlinkage int sys_atomic_barrier(void)
{
 /* no code needed for uniprocs */
 return 0;
}

Messung V0.5
C=95 H=79 G=87

¤ 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.0.16Bemerkung:  (vorverarbeitet)  ¤

*Bot Zugriff






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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge