|
@@ -1382,17 +1382,20 @@ static void gmap_unshadow(struct gmap *sg)
|
|
|
* 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
|
|
|
*/
|
|
|
-static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce)
|
|
|
+static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce,
|
|
|
+ int edat_level)
|
|
|
{
|
|
|
struct gmap *sg;
|
|
|
|
|
|
list_for_each_entry(sg, &parent->children, list) {
|
|
|
- if (sg->orig_asce != asce || sg->removed)
|
|
|
+ if (sg->orig_asce != asce || sg->edat_level != edat_level ||
|
|
|
+ sg->removed)
|
|
|
continue;
|
|
|
if (!sg->initialized)
|
|
|
return ERR_PTR(-EAGAIN);
|
|
@@ -1406,6 +1409,7 @@ static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce)
|
|
|
* 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.
|
|
@@ -1416,7 +1420,8 @@ static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce)
|
|
|
* 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)
|
|
|
+struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
|
|
|
+ int edat_level)
|
|
|
{
|
|
|
struct gmap *sg, *new;
|
|
|
unsigned long limit;
|
|
@@ -1424,7 +1429,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce)
|
|
|
|
|
|
BUG_ON(gmap_is_shadow(parent));
|
|
|
spin_lock(&parent->shadow_lock);
|
|
|
- sg = gmap_find_shadow(parent, asce);
|
|
|
+ sg = gmap_find_shadow(parent, asce, edat_level);
|
|
|
spin_unlock(&parent->shadow_lock);
|
|
|
if (sg)
|
|
|
return sg;
|
|
@@ -1436,10 +1441,11 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce)
|
|
|
new->mm = parent->mm;
|
|
|
new->parent = gmap_get(parent);
|
|
|
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);
|
|
|
+ sg = gmap_find_shadow(parent, asce, edat_level);
|
|
|
if (sg) {
|
|
|
spin_unlock(&parent->shadow_lock);
|
|
|
gmap_free(new);
|