mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/shadow: sh_{write,cmpxchg}_guest_entry() are PV-only
Move them to a new pv.c. Make the respective struct shadow_paging_mode fields as well as the paging.h wrappers PV-only as well. Take the liberty and switch both functions' "failed" local variables to more appropriate types. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Tim Deegan <tim@xen.org>
This commit is contained in:
1 parent
f1f20bb3fa
commit
06f04f54ba
6 files changed
+91
-49
No files matched your search
@@ -146,7 +146,9 @@
|
||||
#include <asm/pv/grant_table.h>
|
||||
#include <asm/pv/mm.h>
|
||||
|
||||
#ifdef CONFIG_PV
|
||||
#include "pv/mm.h"
|
||||
#endif
|
||||
|
||||
/* Override macros from asm/page.h to make them work with mfn_t */
|
||||
#undef virt_to_mfn
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
ifeq ($(CONFIG_SHADOW_PAGING),y)
|
||||
obj-y += common.o guest_2.o guest_3.o guest_4.o
|
||||
obj-$(CONFIG_HVM) += hvm.o
|
||||
obj-$(CONFIG_PV) += pv.o
|
||||
else
|
||||
obj-y += none.o
|
||||
endif
|
||||
|
||||
@@ -372,55 +372,6 @@ static void sh_audit_gw(struct vcpu *v, const walk_t *gw)
|
||||
#endif /* SHADOW_AUDIT & SHADOW_AUDIT_ENTRIES */
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a new value into the guest pagetable, and update the shadows
|
||||
* appropriately. Returns false if we page-faulted, true for success.
|
||||
*/
|
||||
static bool
|
||||
sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new, mfn_t gmfn)
|
||||
{
|
||||
#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
|
||||
int failed;
|
||||
|
||||
paging_lock(v->domain);
|
||||
failed = __copy_to_user(p, &new, sizeof(new));
|
||||
if ( failed != sizeof(new) )
|
||||
sh_validate_guest_entry(v, gmfn, p, sizeof(new));
|
||||
paging_unlock(v->domain);
|
||||
|
||||
return !failed;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Cmpxchg a new value into the guest pagetable, and update the shadows
|
||||
* appropriately. Returns false if we page-faulted, true if not.
|
||||
* N.B. caller should check the value of "old" to see if the cmpxchg itself
|
||||
* was successful.
|
||||
*/
|
||||
static bool
|
||||
sh_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, intpte_t *old,
|
||||
intpte_t new, mfn_t gmfn)
|
||||
{
|
||||
#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
|
||||
int failed;
|
||||
guest_intpte_t t = *old;
|
||||
|
||||
paging_lock(v->domain);
|
||||
failed = cmpxchg_user(p, t, new);
|
||||
if ( t == *old )
|
||||
sh_validate_guest_entry(v, gmfn, p, sizeof(new));
|
||||
*old = t;
|
||||
paging_unlock(v->domain);
|
||||
|
||||
return !failed;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* Functions to compute the correct index into a shadow page, given an
|
||||
* index into the guest page (as returned by guest_get_index()).
|
||||
@@ -4925,8 +4876,10 @@ const struct paging_mode sh_paging_mode = {
|
||||
.write_p2m_entry = shadow_write_p2m_entry,
|
||||
.guest_levels = GUEST_PAGING_LEVELS,
|
||||
.shadow.detach_old_tables = sh_detach_old_tables,
|
||||
#ifdef CONFIG_PV
|
||||
.shadow.write_guest_entry = sh_write_guest_entry,
|
||||
.shadow.cmpxchg_guest_entry = sh_cmpxchg_guest_entry,
|
||||
#endif
|
||||
.shadow.make_monitor_table = sh_make_monitor_table,
|
||||
.shadow.destroy_monitor_table = sh_destroy_monitor_table,
|
||||
#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
|
||||
|
||||
@@ -372,6 +372,12 @@ int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level);
|
||||
|
||||
/* Functions that atomically write PV guest PT entries */
|
||||
bool sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new,
|
||||
mfn_t gmfn);
|
||||
bool sh_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, intpte_t *old,
|
||||
intpte_t new, mfn_t gmfn);
|
||||
|
||||
/* Update all the things that are derived from the guest's CR0/CR3/CR4.
|
||||
* Called to initialize paging structures if the paging mode
|
||||
* has changed, and when bringing up a VCPU for the first time. */
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/******************************************************************************
|
||||
* arch/x86/mm/shadow/pv.c
|
||||
*
|
||||
* PV-only shadow code (which hence does not need to be multiply compiled).
|
||||
* Parts of this code are Copyright (c) 2006 by XenSource Inc.
|
||||
* Parts of this code are Copyright (c) 2006 by Michael A Fetterman
|
||||
* Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <xen/types.h>
|
||||
#include <asm/shadow.h>
|
||||
#include "private.h"
|
||||
|
||||
/*
|
||||
* Write a new value into the guest pagetable, and update the shadows
|
||||
* appropriately. Returns false if we page-faulted, true for success.
|
||||
*/
|
||||
bool
|
||||
sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new, mfn_t gmfn)
|
||||
{
|
||||
unsigned int failed;
|
||||
|
||||
paging_lock(v->domain);
|
||||
failed = __copy_to_user(p, &new, sizeof(new));
|
||||
if ( failed != sizeof(new) )
|
||||
sh_validate_guest_entry(v, gmfn, p, sizeof(new));
|
||||
paging_unlock(v->domain);
|
||||
|
||||
return !failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cmpxchg a new value into the guest pagetable, and update the shadows
|
||||
* appropriately. Returns false if we page-faulted, true if not.
|
||||
* N.B. caller should check the value of "old" to see if the cmpxchg itself
|
||||
* was successful.
|
||||
*/
|
||||
bool
|
||||
sh_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, intpte_t *old,
|
||||
intpte_t new, mfn_t gmfn)
|
||||
{
|
||||
bool failed;
|
||||
intpte_t t = *old;
|
||||
|
||||
paging_lock(v->domain);
|
||||
failed = cmpxchg_user(p, t, new);
|
||||
if ( t == *old )
|
||||
sh_validate_guest_entry(v, gmfn, p, sizeof(new));
|
||||
*old = t;
|
||||
paging_unlock(v->domain);
|
||||
|
||||
return !failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -86,11 +86,13 @@ struct sh_emulate_ctxt;
|
||||
struct shadow_paging_mode {
|
||||
#ifdef CONFIG_SHADOW_PAGING
|
||||
void (*detach_old_tables )(struct vcpu *v);
|
||||
#ifdef CONFIG_PV
|
||||
bool (*write_guest_entry )(struct vcpu *v, intpte_t *p,
|
||||
intpte_t new, mfn_t gmfn);
|
||||
bool (*cmpxchg_guest_entry )(struct vcpu *v, intpte_t *p,
|
||||
intpte_t *old, intpte_t new,
|
||||
mfn_t gmfn);
|
||||
#endif
|
||||
mfn_t (*make_monitor_table )(struct vcpu *v);
|
||||
void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
|
||||
int (*guess_wrmap )(struct vcpu *v,
|
||||
@@ -290,6 +292,7 @@ static inline void paging_update_paging_modes(struct vcpu *v)
|
||||
paging_get_hostmode(v)->update_paging_modes(v);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PV
|
||||
|
||||
/*
|
||||
* Write a new value into the guest pagetable, and update the
|
||||
@@ -325,6 +328,8 @@ static inline bool paging_cmpxchg_guest_entry(
|
||||
return !cmpxchg_user(p, *old, new);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PV */
|
||||
|
||||
/* Helper function that writes a pte in such a way that a concurrent read
|
||||
* never sees a half-written entry that has _PAGE_PRESENT set */
|
||||
static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new)
|
||||
|
||||