aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-04-18 10:22:24 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-20 03:55:02 -0400
commit3218f7094b6b583f4f01bffcf84572c6beacdcc2 (patch)
tree4ebcd767692fccf684503c8202c00cc87dba3472 /arch/s390/mm
parent1c65781b56ce812ce9729bf414201921c9408678 (diff)
s390/mm: support real-space for gmap shadows
We can easily support real-space designation just like EDAT1 and EDAT2. So guest2 can provide for guest3 an asce with the real-space control being set. We simply have to allocate the biggest page table possible and fake all levels. There is no protection to consider. If we exceed guest memory, vsie code will inject an addressing exception (via program intercept). In the future, we could limit the fake table level to the gmap page table. As the top level page table can never go away, such gmap shadows will never get unshadowed, we'll have to come up with another way to limit the number of kept gmap shadows. Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/gmap.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index c96bf30245c0..c07d64f5cdb5 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -1437,6 +1437,8 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
1437 return sg; 1437 return sg;
1438 /* Create a new shadow gmap */ 1438 /* Create a new shadow gmap */
1439 limit = -1UL >> (33 - (((asce & _ASCE_TYPE_MASK) >> 2) * 11)); 1439 limit = -1UL >> (33 - (((asce & _ASCE_TYPE_MASK) >> 2) * 11));
1440 if (asce & _ASCE_REAL_SPACE)
1441 limit = -1UL;
1440 new = gmap_alloc(limit); 1442 new = gmap_alloc(limit);
1441 if (!new) 1443 if (!new)
1442 return ERR_PTR(-ENOMEM); 1444 return ERR_PTR(-ENOMEM);
@@ -1455,6 +1457,12 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
1455 } 1457 }
1456 atomic_set(&new->ref_count, 2); 1458 atomic_set(&new->ref_count, 2);
1457 list_add(&new->list, &parent->children); 1459 list_add(&new->list, &parent->children);
1460 if (asce & _ASCE_REAL_SPACE) {
1461 /* nothing to protect, return right away */
1462 new->initialized = true;
1463 spin_unlock(&parent->shadow_lock);
1464 return new;
1465 }
1458 spin_unlock(&parent->shadow_lock); 1466 spin_unlock(&parent->shadow_lock);
1459 /* protect after insertion, so it will get properly invalidated */ 1467 /* protect after insertion, so it will get properly invalidated */
1460 down_read(&parent->mm->mmap_sem); 1468 down_read(&parent->mm->mmap_sem);
@@ -1479,6 +1487,7 @@ EXPORT_SYMBOL_GPL(gmap_shadow);
1479 * @sg: pointer to the shadow guest address space structure 1487 * @sg: pointer to the shadow guest address space structure
1480 * @saddr: faulting address in the shadow gmap 1488 * @saddr: faulting address in the shadow gmap
1481 * @r2t: parent gmap address of the region 2 table to get shadowed 1489 * @r2t: parent gmap address of the region 2 table to get shadowed
1490 * @fake: r2t references contiguous guest memory block, not a r2t
1482 * 1491 *
1483 * The r2t parameter specifies the address of the source table. The 1492 * The r2t parameter specifies the address of the source table. The
1484 * four pages of the source table are made read-only in the parent gmap 1493 * four pages of the source table are made read-only in the parent gmap
@@ -1491,7 +1500,8 @@ EXPORT_SYMBOL_GPL(gmap_shadow);
1491 * 1500 *
1492 * Called with sg->mm->mmap_sem in read. 1501 * Called with sg->mm->mmap_sem in read.
1493 */ 1502 */
1494int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t) 1503int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t,
1504 int fake)
1495{ 1505{
1496 unsigned long raddr, origin, offset, len; 1506 unsigned long raddr, origin, offset, len;
1497 unsigned long *s_r2t, *table; 1507 unsigned long *s_r2t, *table;
@@ -1504,6 +1514,8 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t)
1504 if (!page) 1514 if (!page)
1505 return -ENOMEM; 1515 return -ENOMEM;
1506 page->index = r2t & _REGION_ENTRY_ORIGIN; 1516 page->index = r2t & _REGION_ENTRY_ORIGIN;
1517 if (fake)
1518 page->index |= GMAP_SHADOW_FAKE_TABLE;
1507 s_r2t = (unsigned long *) page_to_phys(page); 1519 s_r2t = (unsigned long *) page_to_phys(page);
1508 /* Install shadow region second table */ 1520 /* Install shadow region second table */
1509 spin_lock(&sg->guest_table_lock); 1521 spin_lock(&sg->guest_table_lock);
@@ -1526,6 +1538,12 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t)
1526 if (sg->edat_level >= 1) 1538 if (sg->edat_level >= 1)
1527 *table |= (r2t & _REGION_ENTRY_PROTECT); 1539 *table |= (r2t & _REGION_ENTRY_PROTECT);
1528 list_add(&page->lru, &sg->crst_list); 1540 list_add(&page->lru, &sg->crst_list);
1541 if (fake) {
1542 /* nothing to protect for fake tables */
1543 *table &= ~_REGION_ENTRY_INVALID;
1544 spin_unlock(&sg->guest_table_lock);
1545 return 0;
1546 }
1529 spin_unlock(&sg->guest_table_lock); 1547 spin_unlock(&sg->guest_table_lock);
1530 /* Make r2t read-only in parent gmap page table */ 1548 /* Make r2t read-only in parent gmap page table */
1531 raddr = (saddr & 0xffe0000000000000UL) | _SHADOW_RMAP_REGION1; 1549 raddr = (saddr & 0xffe0000000000000UL) | _SHADOW_RMAP_REGION1;
@@ -1558,6 +1576,7 @@ EXPORT_SYMBOL_GPL(gmap_shadow_r2t);
1558 * @sg: pointer to the shadow guest address space structure 1576 * @sg: pointer to the shadow guest address space structure
1559 * @saddr: faulting address in the shadow gmap 1577 * @saddr: faulting address in the shadow gmap
1560 * @r3t: parent gmap address of the region 3 table to get shadowed 1578 * @r3t: parent gmap address of the region 3 table to get shadowed
1579 * @fake: r3t references contiguous guest memory block, not a r3t
1561 * 1580 *
1562 * Returns 0 if successfully shadowed or already shadowed, -EAGAIN if the 1581 * Returns 0 if successfully shadowed or already shadowed, -EAGAIN if the
1563 * shadow table structure is incomplete, -ENOMEM if out of memory and 1582 * shadow table structure is incomplete, -ENOMEM if out of memory and
@@ -1565,7 +1584,8 @@ EXPORT_SYMBOL_GPL(gmap_shadow_r2t);
1565 * 1584 *
1566 * Called with sg->mm->mmap_sem in read. 1585 * Called with sg->mm->mmap_sem in read.
1567 */ 1586 */
1568int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t) 1587int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t,
1588 int fake)
1569{ 1589{
1570 unsigned long raddr, origin, offset, len; 1590 unsigned long raddr, origin, offset, len;
1571 unsigned long *s_r3t, *table; 1591 unsigned long *s_r3t, *table;
@@ -1578,6 +1598,8 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t)
1578 if (!page) 1598 if (!page)
1579 return -ENOMEM; 1599 return -ENOMEM;
1580 page->index = r3t & _REGION_ENTRY_ORIGIN; 1600 page->index = r3t & _REGION_ENTRY_ORIGIN;
1601 if (fake)
1602 page->index |= GMAP_SHADOW_FAKE_TABLE;
1581 s_r3t = (unsigned long *) page_to_phys(page); 1603 s_r3t = (unsigned long *) page_to_phys(page);
1582 /* Install shadow region second table */ 1604 /* Install shadow region second table */
1583 spin_lock(&sg->guest_table_lock); 1605 spin_lock(&sg->guest_table_lock);
@@ -1599,6 +1621,12 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t)
1599 if (sg->edat_level >= 1) 1621 if (sg->edat_level >= 1)
1600 *table |= (r3t & _REGION_ENTRY_PROTECT); 1622 *table |= (r3t & _REGION_ENTRY_PROTECT);
1601 list_add(&page->lru, &sg->crst_list); 1623 list_add(&page->lru, &sg->crst_list);
1624 if (fake) {
1625 /* nothing to protect for fake tables */
1626 *table &= ~_REGION_ENTRY_INVALID;
1627 spin_unlock(&sg->guest_table_lock);
1628 return 0;
1629 }
1602 spin_unlock(&sg->guest_table_lock); 1630 spin_unlock(&sg->guest_table_lock);
1603 /* Make r3t read-only in parent gmap page table */ 1631 /* Make r3t read-only in parent gmap page table */
1604 raddr = (saddr & 0xfffffc0000000000UL) | _SHADOW_RMAP_REGION2; 1632 raddr = (saddr & 0xfffffc0000000000UL) | _SHADOW_RMAP_REGION2;
@@ -1932,7 +1960,8 @@ static void gmap_shadow_notify(struct gmap *sg, unsigned long vmaddr,
1932 /* Check for top level table */ 1960 /* Check for top level table */
1933 start = sg->orig_asce & _ASCE_ORIGIN; 1961 start = sg->orig_asce & _ASCE_ORIGIN;
1934 end = start + ((sg->orig_asce & _ASCE_TABLE_LENGTH) + 1) * 4096; 1962 end = start + ((sg->orig_asce & _ASCE_TABLE_LENGTH) + 1) * 4096;
1935 if (gaddr >= start && gaddr < end) { 1963 if (!(sg->orig_asce & _ASCE_REAL_SPACE) && gaddr >= start &&
1964 gaddr < end) {
1936 /* The complete shadow table has to go */ 1965 /* The complete shadow table has to go */
1937 gmap_unshadow(sg); 1966 gmap_unshadow(sg);
1938 spin_unlock(&sg->guest_table_lock); 1967 spin_unlock(&sg->guest_table_lock);