mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
p2m: change write_p2m_entry to return an error code
This is in preparation for also changing p2m_entry_modify to return an error code. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Wei Liu <wei.liu2@citrix.com> Reviewed-by: George Dunlap <george.dunlap@citrix.com>
This commit is contained in:
1 parent
c7a4c088ad
commit
0d0f4d78e5
9 files changed
+92
-34
No files matched your search
@@ -708,7 +708,7 @@ static void hap_update_paging_modes(struct vcpu *v)
|
||||
put_gfn(d, cr3_gfn);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
hap_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p,
|
||||
l1_pgentry_t new, unsigned int level)
|
||||
{
|
||||
@@ -746,6 +746,8 @@ hap_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p,
|
||||
|
||||
if ( flush_nestedp2m )
|
||||
p2m_flush_nestedp2m(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long hap_gva_to_gfn_real_mode(
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
/* NESTED VIRT P2M FUNCTIONS */
|
||||
/********************************************/
|
||||
|
||||
void
|
||||
int
|
||||
nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new, unsigned int level)
|
||||
{
|
||||
@@ -87,6 +87,8 @@ nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
flush_tlb_mask(p2m->dirty_cpumask);
|
||||
|
||||
paging_unlock(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
|
||||
+62
-15
@@ -184,6 +184,8 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
|
||||
l1_pgentry_t *p2m_entry, new_entry;
|
||||
void *next;
|
||||
unsigned int flags;
|
||||
int rc;
|
||||
mfn_t mfn;
|
||||
|
||||
if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn,
|
||||
shift, max)) )
|
||||
@@ -194,7 +196,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
|
||||
/* PoD/paging: Not present doesn't imply empty. */
|
||||
if ( !flags )
|
||||
{
|
||||
mfn_t mfn = p2m_alloc_ptp(p2m, level);
|
||||
mfn = p2m_alloc_ptp(p2m, level);
|
||||
|
||||
if ( mfn_eq(mfn, INVALID_MFN) )
|
||||
return -ENOMEM;
|
||||
@@ -202,13 +204,14 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
|
||||
new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
|
||||
|
||||
p2m_add_iommu_flags(&new_entry, level, IOMMUF_readable|IOMMUF_writable);
|
||||
p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
|
||||
if ( rc )
|
||||
goto error;
|
||||
}
|
||||
else if ( flags & _PAGE_PSE )
|
||||
{
|
||||
/* Split superpages pages into smaller ones. */
|
||||
unsigned long pfn = l1e_get_pfn(*p2m_entry);
|
||||
mfn_t mfn;
|
||||
l1_pgentry_t *l1_entry;
|
||||
unsigned int i;
|
||||
|
||||
@@ -250,14 +253,23 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
|
||||
{
|
||||
new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * PAGETABLE_ORDER)),
|
||||
flags);
|
||||
p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level);
|
||||
if ( rc )
|
||||
{
|
||||
unmap_domain_page(l1_entry);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
unmap_domain_page(l1_entry);
|
||||
|
||||
new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
|
||||
p2m_add_iommu_flags(&new_entry, level, IOMMUF_readable|IOMMUF_writable);
|
||||
p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
|
||||
p2m_add_iommu_flags(&new_entry, level,
|
||||
IOMMUF_readable|IOMMUF_writable);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry,
|
||||
level + 1);
|
||||
if ( rc )
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
ASSERT(flags & _PAGE_PRESENT);
|
||||
@@ -268,6 +280,12 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
|
||||
*table = next;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ASSERT(rc && mfn_valid(mfn));
|
||||
ASSERT_UNREACHABLE();
|
||||
p2m_free_ptp(p2m, mfn_to_page(mfn));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -321,7 +339,12 @@ static int p2m_pt_set_recalc_range(struct p2m_domain *p2m,
|
||||
if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) )
|
||||
{
|
||||
set_recalc(l1, e);
|
||||
p2m->write_p2m_entry(p2m, first_gfn, pent, e, level);
|
||||
err = p2m->write_p2m_entry(p2m, first_gfn, pent, e, level);
|
||||
if ( err )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
first_gfn += 1UL << (i * PAGETABLE_ORDER);
|
||||
}
|
||||
@@ -392,14 +415,24 @@ static int do_recalc(struct p2m_domain *p2m, unsigned long gfn)
|
||||
!needs_recalc(l1, ent) )
|
||||
{
|
||||
set_recalc(l1, ent);
|
||||
p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i],
|
||||
ent, level);
|
||||
err = p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i],
|
||||
ent, level);
|
||||
if ( err )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
remainder -= 1UL << ((level - 1) * PAGETABLE_ORDER);
|
||||
}
|
||||
smp_wmb();
|
||||
clear_recalc(l1, e);
|
||||
p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
|
||||
err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
|
||||
if ( err )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
unmap_domain_page((void *)((unsigned long)pent & PAGE_MASK));
|
||||
}
|
||||
@@ -444,7 +477,8 @@ static int do_recalc(struct p2m_domain *p2m, unsigned long gfn)
|
||||
}
|
||||
else
|
||||
clear_recalc(l1, e);
|
||||
p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
|
||||
err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
|
||||
ASSERT(!err);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -595,8 +629,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
|
||||
if ( entry_content.l1 != 0 )
|
||||
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
|
||||
|
||||
p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3);
|
||||
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
|
||||
if ( rc )
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -633,8 +669,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
|
||||
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
|
||||
|
||||
/* level 1 entry */
|
||||
p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1);
|
||||
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
|
||||
if ( rc )
|
||||
goto out;
|
||||
}
|
||||
else if ( page_order == PAGE_ORDER_2M )
|
||||
{
|
||||
@@ -669,8 +707,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
|
||||
if ( entry_content.l1 != 0 )
|
||||
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
|
||||
|
||||
p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2);
|
||||
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
|
||||
if ( rc )
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Track the highest gfn for which we have ever had a valid mapping */
|
||||
@@ -894,8 +934,15 @@ static void p2m_pt_change_entry_type_global(struct p2m_domain *p2m,
|
||||
if ( (l1e_get_flags(e) & _PAGE_PRESENT) &&
|
||||
!needs_recalc(l1, e) )
|
||||
{
|
||||
int rc;
|
||||
|
||||
set_recalc(l1, e);
|
||||
p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4);
|
||||
rc = p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4);
|
||||
if ( rc )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
++changed;
|
||||
}
|
||||
gfn += 1UL << (L4_PAGETABLE_SHIFT - PAGE_SHIFT);
|
||||
|
||||
@@ -932,18 +932,22 @@ void paging_update_nestedmode(struct vcpu *v)
|
||||
}
|
||||
#endif
|
||||
|
||||
void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
{
|
||||
struct domain *d = p2m->domain;
|
||||
struct vcpu *v = current;
|
||||
int rc = 0;
|
||||
|
||||
if ( v->domain != d )
|
||||
v = d->vcpu ? d->vcpu[0] : NULL;
|
||||
if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v) != NULL) )
|
||||
paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level);
|
||||
rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level);
|
||||
else
|
||||
safe_write_pte(p, new);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int paging_set_allocation(struct domain *d, unsigned int pages, bool *preempted)
|
||||
|
||||
@@ -3176,7 +3176,7 @@ static void sh_unshadow_for_p2m_change(struct domain *d, unsigned long gfn,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
@@ -3211,6 +3211,8 @@ shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
#endif
|
||||
|
||||
paging_unlock(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -60,11 +60,12 @@ static void _update_paging_modes(struct vcpu *v)
|
||||
ASSERT_UNREACHABLE();
|
||||
}
|
||||
|
||||
static void _write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
static int _write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static const struct paging_mode sh_paging_none = {
|
||||
|
||||
@@ -372,9 +372,9 @@ extern int sh_remove_write_access(struct domain *d, mfn_t readonly_mfn,
|
||||
unsigned long fault_addr);
|
||||
|
||||
/* Functions that atomically write PT/P2M entries and update state */
|
||||
void shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
|
||||
/* Update all the things that are derived from the guest's CR0/CR3/CR4.
|
||||
* Called to initialize paging structures if the paging mode
|
||||
|
||||
@@ -265,7 +265,7 @@ struct p2m_domain {
|
||||
unsigned long last_gfn);
|
||||
void (*memory_type_changed)(struct p2m_domain *p2m);
|
||||
|
||||
void (*write_p2m_entry)(struct p2m_domain *p2m,
|
||||
int (*write_p2m_entry)(struct p2m_domain *p2m,
|
||||
unsigned long gfn, l1_pgentry_t *p,
|
||||
l1_pgentry_t new, unsigned int level);
|
||||
long (*audit_p2m)(struct p2m_domain *p2m);
|
||||
@@ -837,7 +837,7 @@ void p2m_flush_nestedp2m(struct domain *d);
|
||||
/* Flushes the np2m specified by np2m_base (if it exists) */
|
||||
void np2m_flush_base(struct vcpu *v, unsigned long np2m_base);
|
||||
|
||||
void nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
int nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new, unsigned int level);
|
||||
|
||||
/*
|
||||
|
||||
@@ -124,7 +124,7 @@ struct paging_mode {
|
||||
void (*update_cr3 )(struct vcpu *v, int do_locking,
|
||||
bool noflush);
|
||||
void (*update_paging_modes )(struct vcpu *v);
|
||||
void (*write_p2m_entry )(struct p2m_domain *p2m,
|
||||
int (*write_p2m_entry )(struct p2m_domain *p2m,
|
||||
unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
@@ -340,9 +340,9 @@ static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new)
|
||||
* we are writing. */
|
||||
struct p2m_domain;
|
||||
|
||||
void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
|
||||
/*
|
||||
* Called from the guest to indicate that the a process is being
|
||||
|
||||