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

Quelle  gmap-vsie.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Guest memory management for KVM/s390 nested VMs.
 *
 * Copyright IBM Corp. 2008, 2020, 2024
 *
 *    Author(s): Claudio Imbrenda <imbrenda@linux.ibm.com>
 *               Martin Schwidefsky <schwidefsky@de.ibm.com>
 *               David Hildenbrand <david@redhat.com>
 *               Janosch Frank <frankja@linux.vnet.ibm.com>
 */


#include <linux/compiler.h>
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <linux/pgtable.h>
#include <linux/pagemap.h>
#include <linux/mman.h>

#include <asm/lowcore.h>
#include <asm/gmap.h>
#include <asm/uv.h>

#include "kvm-s390.h"

/**
 * gmap_find_shadow - find a specific asce in the list of shadow tables
 * @parent: pointer to the parent gmap
 * @asce: ASCE for which the shadow table is created
 * @edat_level: edat level to be used for the shadow translation
 *
 * Returns the pointer to a gmap if a shadow table with the given asce is
 * already available, ERR_PTR(-EAGAIN) if another one is just being created,
 * otherwise NULL
 *
 * Context: Called with parent->shadow_lock held
 */

static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce, int edat_level)
{
 struct gmap *sg;

 lockdep_assert_held(&parent->shadow_lock);
 list_for_each_entry(sg, &parent->children, list) {
  if (!gmap_shadow_valid(sg, asce, edat_level))
   continue;
  if (!sg->initialized)
   return ERR_PTR(-EAGAIN);
  refcount_inc(&sg->ref_count);
  return sg;
 }
 return NULL;
}

/**
 * gmap_shadow - create/find a shadow guest address space
 * @parent: pointer to the parent gmap
 * @asce: ASCE for which the shadow table is created
 * @edat_level: edat level to be used for the shadow translation
 *
 * The pages of the top level page table referred by the asce parameter
 * will be set to read-only and marked in the PGSTEs of the kvm process.
 * The shadow table will be removed automatically on any change to the
 * PTE mapping for the source table.
 *
 * Returns a guest address space structure, ERR_PTR(-ENOMEM) if out of memory,
 * ERR_PTR(-EAGAIN) if the caller has to retry and ERR_PTR(-EFAULT) if the
 * parent gmap table could not be protected.
 */

struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, int edat_level)
{
 struct gmap *sg, *new;
 unsigned long limit;
 int rc;

 if (KVM_BUG_ON(parent->mm->context.allow_gmap_hpage_1m, (struct kvm *)parent->private) ||
     KVM_BUG_ON(gmap_is_shadow(parent), (struct kvm *)parent->private))
  return ERR_PTR(-EFAULT);
 spin_lock(&parent->shadow_lock);
 sg = gmap_find_shadow(parent, asce, edat_level);
 spin_unlock(&parent->shadow_lock);
 if (sg)
  return sg;
 /* Create a new shadow gmap */
 limit = -1UL >> (33 - (((asce & _ASCE_TYPE_MASK) >> 2) * 11));
 if (asce & _ASCE_REAL_SPACE)
  limit = -1UL;
 new = gmap_alloc(limit);
 if (!new)
  return ERR_PTR(-ENOMEM);
 new->mm = parent->mm;
 new->parent = gmap_get(parent);
 new->private = parent->private;
 new->orig_asce = asce;
 new->edat_level = edat_level;
 new->initialized = false;
 spin_lock(&parent->shadow_lock);
 /* Recheck if another CPU created the same shadow */
 sg = gmap_find_shadow(parent, asce, edat_level);
 if (sg) {
  spin_unlock(&parent->shadow_lock);
  gmap_free(new);
  return sg;
 }
 if (asce & _ASCE_REAL_SPACE) {
  /* only allow one real-space gmap shadow */
  list_for_each_entry(sg, &parent->children, list) {
   if (sg->orig_asce & _ASCE_REAL_SPACE) {
    spin_lock(&sg->guest_table_lock);
    gmap_unshadow(sg);
    spin_unlock(&sg->guest_table_lock);
    list_del(&sg->list);
    gmap_put(sg);
    break;
   }
  }
 }
 refcount_set(&new->ref_count, 2);
 list_add(&new->list, &parent->children);
 if (asce & _ASCE_REAL_SPACE) {
  /* nothing to protect, return right away */
  new->initialized = true;
  spin_unlock(&parent->shadow_lock);
  return new;
 }
 spin_unlock(&parent->shadow_lock);
 /* protect after insertion, so it will get properly invalidated */
 mmap_read_lock(parent->mm);
 rc = __kvm_s390_mprotect_many(parent, asce & _ASCE_ORIGIN,
          ((asce & _ASCE_TABLE_LENGTH) + 1),
          PROT_READ, GMAP_NOTIFY_SHADOW);
 mmap_read_unlock(parent->mm);
 spin_lock(&parent->shadow_lock);
 new->initialized = true;
 if (rc) {
  list_del(&new->list);
  gmap_free(new);
  new = ERR_PTR(rc);
 }
 spin_unlock(&parent->shadow_lock);
 return new;
}

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

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