#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
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
#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()).
.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
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. */
--- /dev/null
+/******************************************************************************
+ * 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:
+ */
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,
paging_get_hostmode(v)->update_paging_modes(v);
}
+#ifdef CONFIG_PV
/*
* Write a new value into the guest pagetable, and update the
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)