mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
[XEN] Rename shadow2 to shadow and move the various source
files into a sensible directory hierarchy. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
a1041848b5
commit
99deb3f2fb
25 files changed
+2585
-2630
No files matched your search
@@ -441,7 +441,7 @@ static int xc_hvm_build_internal(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* HVM domains must be put into shadow2 mode at the start of day */
|
||||
/* HVM domains must be put into shadow mode at the start of day */
|
||||
if ( xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_ENABLE,
|
||||
NULL, 0, NULL,
|
||||
XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT |
|
||||
|
||||
+1
-20
@@ -2,6 +2,7 @@ subdir-y += acpi
|
||||
subdir-y += cpu
|
||||
subdir-y += genapic
|
||||
subdir-y += hvm
|
||||
subdir-y += mm
|
||||
subdir-y += oprofile
|
||||
|
||||
subdir-$(x86_32) += x86_32
|
||||
@@ -41,23 +42,6 @@ obj-y += traps.o
|
||||
obj-y += usercopy.o
|
||||
obj-y += x86_emulate.o
|
||||
|
||||
ifneq ($(pae),n)
|
||||
obj-$(x86_32) += shadow2-common.o shadow2_g2_on_s3.o shadow2_g3_on_s3.o
|
||||
else
|
||||
obj-$(x86_32) += shadow2-common.o shadow2_g2_on_s2.o
|
||||
endif
|
||||
|
||||
obj-$(x86_64) += shadow2-common.o shadow2_g4_on_s4.o shadow2_g3_on_s3.o \
|
||||
shadow2_g2_on_s3.o
|
||||
|
||||
guest_levels = $(subst g,,$(filter g%,$(subst ., ,$(subst _, ,$(subst shadow2_,,$(1))))))
|
||||
shadow_levels = $(subst s,,$(filter s%,$(subst ., ,$(subst _, ,$(subst shadow2_,,$(1))))))
|
||||
shadow2_defns = -DGUEST_PAGING_LEVELS=$(call guest_levels,$(1)) \
|
||||
-DSHADOW_PAGING_LEVELS=$(call shadow_levels,$(1))
|
||||
|
||||
shadow2_%.o: shadow2.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) $(call shadow2_defns,$(@F)) -c $< -o $@
|
||||
|
||||
obj-$(crash_debug) += gdbstub.o
|
||||
|
||||
$(TARGET): $(TARGET)-syms boot/mkelf32
|
||||
@@ -86,9 +70,6 @@ xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS)
|
||||
boot/mkelf32: boot/mkelf32.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
|
||||
|
||||
shadow_guest32.o: shadow.c
|
||||
shadow_guest32pae.o: shadow.c
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
rm -f asm-offsets.s xen.lds boot/*.o boot/*~ boot/core boot/mkelf32
|
||||
+22
-22
@@ -200,12 +200,12 @@ int arch_domain_create(struct domain *d)
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
shadow2_lock_init(d);
|
||||
for ( i = 0; i <= SHADOW2_MAX_ORDER; i++ )
|
||||
INIT_LIST_HEAD(&d->arch.shadow2.freelists[i]);
|
||||
INIT_LIST_HEAD(&d->arch.shadow2.p2m_freelist);
|
||||
INIT_LIST_HEAD(&d->arch.shadow2.p2m_inuse);
|
||||
INIT_LIST_HEAD(&d->arch.shadow2.toplevel_shadows);
|
||||
shadow_lock_init(d);
|
||||
for ( i = 0; i <= SHADOW_MAX_ORDER; i++ )
|
||||
INIT_LIST_HEAD(&d->arch.shadow.freelists[i]);
|
||||
INIT_LIST_HEAD(&d->arch.shadow.p2m_freelist);
|
||||
INIT_LIST_HEAD(&d->arch.shadow.p2m_inuse);
|
||||
INIT_LIST_HEAD(&d->arch.shadow.toplevel_shadows);
|
||||
|
||||
if ( !is_idle_domain(d) )
|
||||
{
|
||||
@@ -236,7 +236,7 @@ int arch_domain_create(struct domain *d)
|
||||
|
||||
void arch_domain_destroy(struct domain *d)
|
||||
{
|
||||
shadow2_final_teardown(d);
|
||||
shadow_final_teardown(d);
|
||||
|
||||
free_xenheap_pages(
|
||||
d->arch.mm_perdomain_pt,
|
||||
@@ -342,10 +342,10 @@ int arch_set_info_guest(
|
||||
}
|
||||
}
|
||||
|
||||
/* Shadow2: make sure the domain has enough shadow memory to
|
||||
/* Shadow: make sure the domain has enough shadow memory to
|
||||
* boot another vcpu */
|
||||
if ( shadow2_mode_enabled(d)
|
||||
&& d->arch.shadow2.total_pages < shadow2_min_acceptable_pages(d) )
|
||||
if ( shadow_mode_enabled(d)
|
||||
&& d->arch.shadow.total_pages < shadow_min_acceptable_pages(d) )
|
||||
{
|
||||
destroy_gdt(v);
|
||||
return -ENOMEM;
|
||||
@@ -357,8 +357,8 @@ int arch_set_info_guest(
|
||||
/* Don't redo final setup */
|
||||
set_bit(_VCPUF_initialised, &v->vcpu_flags);
|
||||
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
shadow2_update_paging_modes(v);
|
||||
if ( shadow_mode_enabled(d) )
|
||||
shadow_update_paging_modes(v);
|
||||
|
||||
update_cr3(v);
|
||||
|
||||
@@ -936,11 +936,11 @@ void domain_relinquish_resources(struct domain *d)
|
||||
for_each_vcpu ( d, v )
|
||||
{
|
||||
/* Drop ref to guest_table (from new_guest_cr3(), svm/vmx cr3 handling,
|
||||
* or sh2_update_paging_modes()) */
|
||||
* or sh_update_paging_modes()) */
|
||||
pfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
if ( pfn != 0 )
|
||||
{
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
put_page(mfn_to_page(pfn));
|
||||
else
|
||||
put_page_and_type(mfn_to_page(pfn));
|
||||
@@ -962,7 +962,7 @@ void domain_relinquish_resources(struct domain *d)
|
||||
hvm_relinquish_guest_resources(d);
|
||||
|
||||
/* Tear down shadow mode stuff. */
|
||||
shadow2_teardown(d);
|
||||
shadow_teardown(d);
|
||||
|
||||
/*
|
||||
* Relinquish GDT mappings. No need for explicit unmapping of the LDT as
|
||||
@@ -981,18 +981,18 @@ void domain_relinquish_resources(struct domain *d)
|
||||
|
||||
void arch_dump_domain_info(struct domain *d)
|
||||
{
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
if ( shadow_mode_enabled(d) )
|
||||
{
|
||||
printk(" shadow2 mode: ");
|
||||
if ( d->arch.shadow2.mode & SHM2_enable )
|
||||
printk(" shadow mode: ");
|
||||
if ( d->arch.shadow.mode & SHM2_enable )
|
||||
printk("enabled ");
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
printk("refcounts ");
|
||||
if ( shadow2_mode_log_dirty(d) )
|
||||
if ( shadow_mode_log_dirty(d) )
|
||||
printk("log_dirty ");
|
||||
if ( shadow2_mode_translate(d) )
|
||||
if ( shadow_mode_translate(d) )
|
||||
printk("translate ");
|
||||
if ( shadow2_mode_external(d) )
|
||||
if ( shadow_mode_external(d) )
|
||||
printk("external ");
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
@@ -679,8 +679,8 @@ int construct_dom0(struct domain *d,
|
||||
(void)alloc_vcpu(d, i, i);
|
||||
|
||||
/* Set up CR3 value for write_ptbase */
|
||||
if ( shadow2_mode_enabled(v->domain) )
|
||||
shadow2_update_paging_modes(v);
|
||||
if ( shadow_mode_enabled(v->domain) )
|
||||
shadow_update_paging_modes(v);
|
||||
else
|
||||
update_cr3(v);
|
||||
|
||||
@@ -791,8 +791,8 @@ int construct_dom0(struct domain *d,
|
||||
new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
|
||||
|
||||
if ( opt_dom0_shadow )
|
||||
if ( shadow2_test_enable(d) == 0 )
|
||||
shadow2_update_paging_modes(v);
|
||||
if ( shadow_test_enable(d) == 0 )
|
||||
shadow_update_paging_modes(v);
|
||||
|
||||
if ( supervisor_mode_kernel )
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ long arch_do_domctl(
|
||||
d = find_domain_by_id(domctl->domain);
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = shadow2_domctl(d, &domctl->u.shadow_op, u_domctl);
|
||||
ret = shadow_domctl(d, &domctl->u.shadow_op, u_domctl);
|
||||
put_domain(d);
|
||||
copy_to_guest(u_domctl, domctl, 1);
|
||||
}
|
||||
|
||||
@@ -384,8 +384,8 @@ int hvm_copy(void *buf, unsigned long vaddr, int size, int dir)
|
||||
if (count > size)
|
||||
count = size;
|
||||
|
||||
gfn = shadow2_gva_to_gfn(v, vaddr);
|
||||
mfn = mfn_x(sh2_vcpu_gfn_to_mfn(v, gfn));
|
||||
gfn = shadow_gva_to_gfn(v, vaddr);
|
||||
mfn = mfn_x(sh_vcpu_gfn_to_mfn(v, gfn));
|
||||
|
||||
if (mfn == INVALID_MFN)
|
||||
return 0;
|
||||
@@ -539,7 +539,7 @@ void hvm_do_hypercall(struct cpu_user_regs *pregs)
|
||||
return;
|
||||
}
|
||||
|
||||
if ( current->arch.shadow2.mode->guest_levels == 4 )
|
||||
if ( current->arch.shadow.mode->guest_levels == 4 )
|
||||
{
|
||||
pregs->rax = hvm_hypercall64_table[pregs->rax](pregs->rdi,
|
||||
pregs->rsi,
|
||||
|
||||
@@ -721,7 +721,7 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
|
||||
|
||||
if (pvalid) {
|
||||
if (hvm_paging_enabled(current))
|
||||
p->u.data = shadow2_gva_to_gpa(current, value);
|
||||
p->u.data = shadow_gva_to_gpa(current, value);
|
||||
else
|
||||
p->u.pdata = (void *) value; /* guest VA == guest PA */
|
||||
} else
|
||||
@@ -771,7 +771,7 @@ void send_mmio_req(
|
||||
|
||||
if (pvalid) {
|
||||
if (hvm_paging_enabled(v))
|
||||
p->u.data = shadow2_gva_to_gpa(v, value);
|
||||
p->u.data = shadow_gva_to_gpa(v, value);
|
||||
else
|
||||
p->u.pdata = (void *) value; /* guest VA == guest PA */
|
||||
} else
|
||||
|
||||
+14
-14
@@ -29,7 +29,7 @@
|
||||
#include <xen/domain_page.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/shadow2.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -746,10 +746,10 @@ static void svm_final_setup_guest(struct vcpu *v)
|
||||
if ( v != d->vcpu[0] )
|
||||
return;
|
||||
|
||||
if ( !shadow2_mode_external(d) )
|
||||
if ( !shadow_mode_external(d) )
|
||||
{
|
||||
DPRINTK("Can't init HVM for dom %u vcpu %u: "
|
||||
"not in shadow2 external mode\n", d->domain_id, v->vcpu_id);
|
||||
"not in shadow external mode\n", d->domain_id, v->vcpu_id);
|
||||
domain_crash(d);
|
||||
}
|
||||
|
||||
@@ -914,7 +914,7 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
va, eip, (unsigned long)regs->error_code);
|
||||
//#endif
|
||||
|
||||
result = shadow2_fault(va, regs);
|
||||
result = shadow_fault(va, regs);
|
||||
|
||||
if( result ) {
|
||||
/* Let's make sure that the Guest TLB is flushed */
|
||||
@@ -1562,7 +1562,7 @@ static int svm_set_cr0(unsigned long value)
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
if ( old_base_mfn )
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
|
||||
(unsigned long) (mfn << PAGE_SHIFT));
|
||||
@@ -1588,14 +1588,14 @@ static int svm_set_cr0(unsigned long value)
|
||||
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
}
|
||||
else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
|
||||
{
|
||||
/* we should take care of this kind of situation */
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
}
|
||||
@@ -1706,7 +1706,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if (mfn != pagetable_get_pfn(v->arch.guest_table))
|
||||
__hvm_bug(regs);
|
||||
shadow2_update_cr3(v);
|
||||
shadow_update_cr3(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1771,7 +1771,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
if ( old_base_mfn )
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
|
||||
(unsigned long) (mfn << PAGE_SHIFT));
|
||||
@@ -1808,7 +1808,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
|
||||
{
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2149,7 +2149,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
|
||||
|
||||
/* Overkill, we may not this */
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
shadow2_invlpg(v, g_vaddr);
|
||||
shadow_invlpg(v, g_vaddr);
|
||||
}
|
||||
|
||||
|
||||
@@ -2520,7 +2520,7 @@ void walk_shadow_and_guest_pt(unsigned long gva)
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
unsigned long gpa;
|
||||
|
||||
gpa = shadow2_gva_to_gpa(current, gva);
|
||||
gpa = shadow_gva_to_gpa(current, gva);
|
||||
printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
|
||||
if( !svm_paging_enabled(v) || mmio_space(gpa) )
|
||||
return;
|
||||
@@ -2591,7 +2591,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
|
||||
{
|
||||
if (svm_paging_enabled(v) &&
|
||||
!mmio_space(shadow2_gva_to_gpa(current, vmcb->exitinfo2)))
|
||||
!mmio_space(shadow_gva_to_gpa(current, vmcb->exitinfo2)))
|
||||
{
|
||||
printk("I%08ld,ExC=%s(%d),IP=%x:%llx,"
|
||||
"I1=%llx,I2=%llx,INT=%llx, "
|
||||
@@ -2601,7 +2601,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
(unsigned long long) vmcb->exitinfo1,
|
||||
(unsigned long long) vmcb->exitinfo2,
|
||||
(unsigned long long) vmcb->exitintinfo.bytes,
|
||||
(unsigned long long) shadow2_gva_to_gpa(current, vmcb->exitinfo2));
|
||||
(unsigned long long) shadow_gva_to_gpa(current, vmcb->exitinfo2));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <xen/event.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/keyhandler.h>
|
||||
#include <asm/shadow2.h>
|
||||
#include <asm/shadow.h>
|
||||
|
||||
static int vmcs_size;
|
||||
static int vmcs_order;
|
||||
@@ -272,7 +272,7 @@ static void vmx_do_launch(struct vcpu *v)
|
||||
error |= __vmwrite(GUEST_TR_BASE, 0);
|
||||
error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
|
||||
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
printk("%s(): GUEST_CR3<=%08lx, HOST_CR3<=%08lx\n",
|
||||
__func__, v->arch.hvm_vcpu.hw_cr3, v->arch.cr3);
|
||||
__vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
|
||||
|
||||
+10
-10
@@ -40,7 +40,7 @@
|
||||
#include <asm/hvm/vmx/vmx.h>
|
||||
#include <asm/hvm/vmx/vmcs.h>
|
||||
#include <asm/hvm/vmx/cpu.h>
|
||||
#include <asm/shadow2.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <public/sched.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/hvm/vpic.h>
|
||||
@@ -66,10 +66,10 @@ static int vmx_initialize_guest_resources(struct vcpu *v)
|
||||
if ( v->vcpu_id != 0 )
|
||||
return 1;
|
||||
|
||||
if ( !shadow2_mode_external(d) )
|
||||
if ( !shadow_mode_external(d) )
|
||||
{
|
||||
DPRINTK("Can't init HVM for dom %u vcpu %u: "
|
||||
"not in shadow2 external mode\n",
|
||||
"not in shadow external mode\n",
|
||||
d->domain_id, v->vcpu_id);
|
||||
domain_crash(d);
|
||||
}
|
||||
@@ -865,7 +865,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
}
|
||||
#endif
|
||||
|
||||
result = shadow2_fault(va, regs);
|
||||
result = shadow_fault(va, regs);
|
||||
|
||||
TRACE_VMEXIT (2,result);
|
||||
#if 0
|
||||
@@ -1039,7 +1039,7 @@ static void vmx_vmexit_do_invlpg(unsigned long va)
|
||||
* We do the safest things first, then try to update the shadow
|
||||
* copying from guest
|
||||
*/
|
||||
shadow2_invlpg(v, va);
|
||||
shadow_invlpg(v, va);
|
||||
}
|
||||
|
||||
|
||||
@@ -1301,7 +1301,7 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
|
||||
skip_cr3:
|
||||
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
if (!vmx_paging_enabled(v))
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
|
||||
else
|
||||
@@ -1504,7 +1504,7 @@ static int vmx_set_cr0(unsigned long value)
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
if (old_base_mfn)
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
|
||||
(unsigned long) (mfn << PAGE_SHIFT));
|
||||
@@ -1577,7 +1577,7 @@ static int vmx_set_cr0(unsigned long value)
|
||||
else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
|
||||
{
|
||||
__vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1662,7 +1662,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if (mfn != pagetable_get_pfn(v->arch.guest_table))
|
||||
__hvm_bug(regs);
|
||||
shadow2_update_cr3(v);
|
||||
shadow_update_cr3(v);
|
||||
} else {
|
||||
/*
|
||||
* If different, make a shadow. Check if the PDBR is valid
|
||||
@@ -1755,7 +1755,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
* all TLB entries except global entries.
|
||||
*/
|
||||
if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) )
|
||||
shadow2_update_paging_modes(v);
|
||||
shadow_update_paging_modes(v);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
+68
-68
@@ -454,12 +454,12 @@ int map_ldt_shadow_page(unsigned int off)
|
||||
|
||||
res = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page);
|
||||
|
||||
if ( !res && unlikely(shadow2_mode_refcounts(d)) )
|
||||
if ( !res && unlikely(shadow_mode_refcounts(d)) )
|
||||
{
|
||||
shadow2_lock(d);
|
||||
shadow2_remove_write_access(d->vcpu[0], _mfn(mfn), 0, 0);
|
||||
shadow_lock(d);
|
||||
shadow_remove_write_access(d->vcpu[0], _mfn(mfn), 0, 0);
|
||||
res = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page);
|
||||
shadow2_unlock(d);
|
||||
shadow_unlock(d);
|
||||
}
|
||||
|
||||
if ( unlikely(!res) )
|
||||
@@ -527,7 +527,7 @@ get_linear_pagetable(
|
||||
struct page_info *page;
|
||||
unsigned long pfn;
|
||||
|
||||
ASSERT( !shadow2_mode_refcounts(d) );
|
||||
ASSERT( !shadow_mode_refcounts(d) );
|
||||
|
||||
if ( (root_get_flags(re) & _PAGE_RW) )
|
||||
{
|
||||
@@ -602,12 +602,12 @@ get_page_from_l1e(
|
||||
d = dom_io;
|
||||
}
|
||||
|
||||
/* Foreign mappings into guests in shadow2 external mode don't
|
||||
/* Foreign mappings into guests in shadow external mode don't
|
||||
* contribute to writeable mapping refcounts. (This allows the
|
||||
* qemu-dm helper process in dom0 to map the domain's memory without
|
||||
* messing up the count of "real" writable mappings.) */
|
||||
okay = (((l1e_get_flags(l1e) & _PAGE_RW) &&
|
||||
!(unlikely(shadow2_mode_external(d) && (d != current->domain))))
|
||||
!(unlikely(shadow_mode_external(d) && (d != current->domain))))
|
||||
? get_page_and_type(page, d, PGT_writable_page)
|
||||
: get_page(page, d));
|
||||
if ( !okay )
|
||||
@@ -771,9 +771,9 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
|
||||
}
|
||||
|
||||
/* Remember we didn't take a type-count of foreign writable mappings
|
||||
* to shadow2 external domains */
|
||||
* to shadow external domains */
|
||||
if ( (l1e_get_flags(l1e) & _PAGE_RW) &&
|
||||
!(unlikely((e != d) && shadow2_mode_external(e))) )
|
||||
!(unlikely((e != d) && shadow_mode_external(e))) )
|
||||
{
|
||||
put_page_and_type(page);
|
||||
}
|
||||
@@ -830,7 +830,7 @@ static int alloc_l1_table(struct page_info *page)
|
||||
l1_pgentry_t *pl1e;
|
||||
int i;
|
||||
|
||||
ASSERT(!shadow2_mode_refcounts(d));
|
||||
ASSERT(!shadow_mode_refcounts(d));
|
||||
|
||||
pl1e = map_domain_page(pfn);
|
||||
|
||||
@@ -883,7 +883,7 @@ static int create_pae_xen_mappings(l3_pgentry_t *pl3e)
|
||||
* a. alloc_l3_table() calls this function and this check will fail
|
||||
* b. mod_l3_entry() disallows updates to slot 3 in an existing table
|
||||
*
|
||||
* XXX -- this needs revisiting for shadow2_mode_refcount()==true...
|
||||
* XXX -- this needs revisiting for shadow_mode_refcount()==true...
|
||||
*/
|
||||
page = l3e_get_page(l3e3);
|
||||
BUG_ON(page->u.inuse.type_info & PGT_pinned);
|
||||
@@ -1007,7 +1007,7 @@ static int alloc_l2_table(struct page_info *page, unsigned long type)
|
||||
l2_pgentry_t *pl2e;
|
||||
int i;
|
||||
|
||||
ASSERT(!shadow2_mode_refcounts(d));
|
||||
ASSERT(!shadow_mode_refcounts(d));
|
||||
|
||||
pl2e = map_domain_page(pfn);
|
||||
|
||||
@@ -1059,7 +1059,7 @@ static int alloc_l3_table(struct page_info *page, unsigned long type)
|
||||
l3_pgentry_t *pl3e;
|
||||
int i;
|
||||
|
||||
ASSERT(!shadow2_mode_refcounts(d));
|
||||
ASSERT(!shadow_mode_refcounts(d));
|
||||
|
||||
#ifdef CONFIG_X86_PAE
|
||||
/*
|
||||
@@ -1120,7 +1120,7 @@ static int alloc_l4_table(struct page_info *page, unsigned long type)
|
||||
unsigned long vaddr;
|
||||
int i;
|
||||
|
||||
ASSERT(!shadow2_mode_refcounts(d));
|
||||
ASSERT(!shadow_mode_refcounts(d));
|
||||
|
||||
for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
|
||||
{
|
||||
@@ -1234,8 +1234,8 @@ static inline int update_l1e(l1_pgentry_t *pl1e,
|
||||
struct vcpu *v)
|
||||
{
|
||||
int rv = 1;
|
||||
if ( unlikely(shadow2_mode_enabled(v->domain)) )
|
||||
shadow2_lock(v->domain);
|
||||
if ( unlikely(shadow_mode_enabled(v->domain)) )
|
||||
shadow_lock(v->domain);
|
||||
#ifndef PTE_UPDATE_WITH_CMPXCHG
|
||||
rv = (!__copy_to_user(pl1e, &nl1e, sizeof(nl1e)));
|
||||
#else
|
||||
@@ -1266,10 +1266,10 @@ static inline int update_l1e(l1_pgentry_t *pl1e,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ( unlikely(shadow2_mode_enabled(v->domain)) )
|
||||
if ( unlikely(shadow_mode_enabled(v->domain)) )
|
||||
{
|
||||
shadow2_validate_guest_entry(v, _mfn(gl1mfn), pl1e);
|
||||
shadow2_unlock(v->domain);
|
||||
shadow_validate_guest_entry(v, _mfn(gl1mfn), pl1e);
|
||||
shadow_unlock(v->domain);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -1339,13 +1339,13 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
|
||||
#endif
|
||||
#define UPDATE_ENTRY(_t,_p,_o,_n,_m) ({ \
|
||||
int rv; \
|
||||
if ( unlikely(shadow2_mode_enabled(current->domain)) ) \
|
||||
shadow2_lock(current->domain); \
|
||||
if ( unlikely(shadow_mode_enabled(current->domain)) ) \
|
||||
shadow_lock(current->domain); \
|
||||
rv = _UPDATE_ENTRY(_t, _p, _o, _n); \
|
||||
if ( unlikely(shadow2_mode_enabled(current->domain)) ) \
|
||||
if ( unlikely(shadow_mode_enabled(current->domain)) ) \
|
||||
{ \
|
||||
shadow2_validate_guest_entry(current, _mfn(_m), (_p)); \
|
||||
shadow2_unlock(current->domain); \
|
||||
shadow_validate_guest_entry(current, _mfn(_m), (_p)); \
|
||||
shadow_unlock(current->domain); \
|
||||
} \
|
||||
rv; \
|
||||
})
|
||||
@@ -1581,21 +1581,21 @@ void free_page_type(struct page_info *page, unsigned long type)
|
||||
*/
|
||||
this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_ALL_TLBS;
|
||||
|
||||
if ( unlikely(shadow2_mode_enabled(owner)
|
||||
&& !shadow2_lock_is_acquired(owner)) )
|
||||
if ( unlikely(shadow_mode_enabled(owner)
|
||||
&& !shadow_lock_is_acquired(owner)) )
|
||||
{
|
||||
/* Raw page tables are rewritten during save/restore. */
|
||||
if ( !shadow2_mode_translate(owner) )
|
||||
if ( !shadow_mode_translate(owner) )
|
||||
mark_dirty(owner, page_to_mfn(page));
|
||||
|
||||
if ( shadow2_mode_refcounts(owner) )
|
||||
if ( shadow_mode_refcounts(owner) )
|
||||
return;
|
||||
|
||||
gmfn = mfn_to_gmfn(owner, page_to_mfn(page));
|
||||
ASSERT(VALID_M2P(gmfn));
|
||||
shadow2_lock(owner);
|
||||
shadow2_remove_all_shadows(owner->vcpu[0], _mfn(gmfn));
|
||||
shadow2_unlock(owner);
|
||||
shadow_lock(owner);
|
||||
shadow_remove_all_shadows(owner->vcpu[0], _mfn(gmfn));
|
||||
shadow_unlock(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1760,7 +1760,7 @@ int get_page_type(struct page_info *page, unsigned long type)
|
||||
#endif
|
||||
/* Fixme: add code to propagate va_unknown to subtables. */
|
||||
if ( ((type & PGT_type_mask) >= PGT_l2_page_table) &&
|
||||
!shadow2_mode_refcounts(page_get_owner(page)) )
|
||||
!shadow_mode_refcounts(page_get_owner(page)) )
|
||||
return 0;
|
||||
/* This table is possibly mapped at multiple locations. */
|
||||
nx &= ~PGT_va_mask;
|
||||
@@ -1810,7 +1810,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||
if ( hvm_guest(v) && !hvm_paging_enabled(v) )
|
||||
domain_crash_synchronous();
|
||||
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
{
|
||||
okay = get_page_from_pagenr(mfn, d);
|
||||
if ( unlikely(!okay) )
|
||||
@@ -1858,7 +1858,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||
|
||||
if ( likely(old_base_mfn != 0) )
|
||||
{
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
else
|
||||
put_page_and_type(mfn_to_page(old_base_mfn));
|
||||
@@ -2043,7 +2043,7 @@ int do_mmuext_op(
|
||||
type = PGT_root_page_table;
|
||||
|
||||
pin_page:
|
||||
if ( shadow2_mode_refcounts(FOREIGNDOM) )
|
||||
if ( shadow_mode_refcounts(FOREIGNDOM) )
|
||||
break;
|
||||
|
||||
okay = get_page_and_type_from_pagenr(mfn, type, FOREIGNDOM);
|
||||
@@ -2065,7 +2065,7 @@ int do_mmuext_op(
|
||||
break;
|
||||
|
||||
case MMUEXT_UNPIN_TABLE:
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
break;
|
||||
|
||||
if ( unlikely(!(okay = get_page_from_pagenr(mfn, d))) )
|
||||
@@ -2078,11 +2078,11 @@ int do_mmuext_op(
|
||||
{
|
||||
put_page_and_type(page);
|
||||
put_page(page);
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
if ( shadow_mode_enabled(d) )
|
||||
{
|
||||
shadow2_lock(d);
|
||||
shadow2_remove_all_shadows(v, _mfn(mfn));
|
||||
shadow2_unlock(d);
|
||||
shadow_lock(d);
|
||||
shadow_remove_all_shadows(v, _mfn(mfn));
|
||||
shadow_unlock(d);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2125,8 +2125,8 @@ int do_mmuext_op(
|
||||
break;
|
||||
|
||||
case MMUEXT_INVLPG_LOCAL:
|
||||
if ( !shadow2_mode_enabled(d)
|
||||
|| shadow2_invlpg(v, op.arg1.linear_addr) != 0 )
|
||||
if ( !shadow_mode_enabled(d)
|
||||
|| shadow_invlpg(v, op.arg1.linear_addr) != 0 )
|
||||
local_flush_tlb_one(op.arg1.linear_addr);
|
||||
break;
|
||||
|
||||
@@ -2173,7 +2173,7 @@ int do_mmuext_op(
|
||||
unsigned long ptr = op.arg1.linear_addr;
|
||||
unsigned long ents = op.arg2.nr_ents;
|
||||
|
||||
if ( shadow2_mode_external(d) )
|
||||
if ( shadow_mode_external(d) )
|
||||
{
|
||||
MEM_LOG("ignoring SET_LDT hypercall from external "
|
||||
"domain %u", d->domain_id);
|
||||
@@ -2319,7 +2319,7 @@ int do_mmu_update(
|
||||
case PGT_l3_page_table:
|
||||
case PGT_l4_page_table:
|
||||
{
|
||||
if ( shadow2_mode_refcounts(d) )
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
{
|
||||
DPRINTK("mmu update on shadow-refcounted domain!");
|
||||
break;
|
||||
@@ -2372,16 +2372,16 @@ int do_mmu_update(
|
||||
if ( unlikely(!get_page_type(page, PGT_writable_page)) )
|
||||
break;
|
||||
|
||||
if ( unlikely(shadow2_mode_enabled(d)) )
|
||||
shadow2_lock(d);
|
||||
if ( unlikely(shadow_mode_enabled(d)) )
|
||||
shadow_lock(d);
|
||||
|
||||
*(intpte_t *)va = req.val;
|
||||
okay = 1;
|
||||
|
||||
if ( unlikely(shadow2_mode_enabled(d)) )
|
||||
if ( unlikely(shadow_mode_enabled(d)) )
|
||||
{
|
||||
shadow2_validate_guest_entry(v, _mfn(mfn), va);
|
||||
shadow2_unlock(d);
|
||||
shadow_validate_guest_entry(v, _mfn(mfn), va);
|
||||
shadow_unlock(d);
|
||||
}
|
||||
|
||||
put_page_type(page);
|
||||
@@ -2405,8 +2405,8 @@ int do_mmu_update(
|
||||
break;
|
||||
}
|
||||
|
||||
if ( shadow2_mode_translate(FOREIGNDOM) )
|
||||
shadow2_guest_physmap_add_page(FOREIGNDOM, gpfn, mfn);
|
||||
if ( shadow_mode_translate(FOREIGNDOM) )
|
||||
shadow_guest_physmap_add_page(FOREIGNDOM, gpfn, mfn);
|
||||
else
|
||||
set_gpfn_from_mfn(mfn, gpfn);
|
||||
okay = 1;
|
||||
@@ -2492,7 +2492,7 @@ static int create_grant_pte_mapping(
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if ( !shadow2_mode_refcounts(d) )
|
||||
if ( !shadow_mode_refcounts(d) )
|
||||
put_page_from_l1e(ol1e, d);
|
||||
|
||||
put_page_type(page);
|
||||
@@ -2590,7 +2590,7 @@ static int create_grant_va_mapping(
|
||||
l2e_get_pfn(__linear_l2_table[l2_linear_offset(va)]), v) )
|
||||
return GNTST_general_error;
|
||||
|
||||
if ( !shadow2_mode_refcounts(d) )
|
||||
if ( !shadow_mode_refcounts(d) )
|
||||
put_page_from_l1e(ol1e, d);
|
||||
|
||||
return GNTST_okay;
|
||||
@@ -2714,10 +2714,10 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
|
||||
perfc_incrc(calls_to_update_va);
|
||||
|
||||
if ( unlikely(!__addr_ok(va) && !shadow2_mode_external(d)) )
|
||||
if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( unlikely(shadow2_mode_refcounts(d)) )
|
||||
if ( unlikely(shadow_mode_refcounts(d)) )
|
||||
{
|
||||
DPRINTK("Grant op on a shadow-refcounted domain\n");
|
||||
return -EINVAL;
|
||||
@@ -2725,11 +2725,11 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
|
||||
LOCK_BIGLOCK(d);
|
||||
|
||||
if ( likely(rc == 0) && unlikely(shadow2_mode_enabled(d)) )
|
||||
if ( likely(rc == 0) && unlikely(shadow_mode_enabled(d)) )
|
||||
{
|
||||
if ( unlikely(this_cpu(percpu_mm_info).foreign &&
|
||||
(shadow2_mode_translate(d) ||
|
||||
shadow2_mode_translate(
|
||||
(shadow_mode_translate(d) ||
|
||||
shadow_mode_translate(
|
||||
this_cpu(percpu_mm_info).foreign))) )
|
||||
{
|
||||
/*
|
||||
@@ -2770,8 +2770,8 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
switch ( (bmap_ptr = flags & ~UVMF_FLUSHTYPE_MASK) )
|
||||
{
|
||||
case UVMF_LOCAL:
|
||||
if ( !shadow2_mode_enabled(d)
|
||||
|| (shadow2_invlpg(current, va) != 0) )
|
||||
if ( !shadow_mode_enabled(d)
|
||||
|| (shadow_invlpg(current, va) != 0) )
|
||||
local_flush_tlb_one(va);
|
||||
break;
|
||||
case UVMF_ALL:
|
||||
@@ -3006,7 +3006,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !shadow2_mode_translate(d) || (mfn == 0) )
|
||||
if ( !shadow_mode_translate(d) || (mfn == 0) )
|
||||
{
|
||||
put_domain(d);
|
||||
return -EINVAL;
|
||||
@@ -3196,21 +3196,21 @@ static int ptwr_emulated_update(
|
||||
pl1e = (l1_pgentry_t *)((unsigned long)pl1e + (addr & ~PAGE_MASK));
|
||||
if ( do_cmpxchg )
|
||||
{
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
shadow2_lock(d);
|
||||
if ( shadow_mode_enabled(d) )
|
||||
shadow_lock(d);
|
||||
ol1e = l1e_from_intpte(old);
|
||||
if ( cmpxchg((intpte_t *)pl1e, old, val) != old )
|
||||
{
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
shadow2_unlock(d);
|
||||
if ( shadow_mode_enabled(d) )
|
||||
shadow_unlock(d);
|
||||
unmap_domain_page(pl1e);
|
||||
put_page_from_l1e(nl1e, d);
|
||||
return X86EMUL_CMPXCHG_FAILED;
|
||||
}
|
||||
if ( unlikely(shadow2_mode_enabled(v->domain)) )
|
||||
if ( unlikely(shadow_mode_enabled(v->domain)) )
|
||||
{
|
||||
shadow2_validate_guest_entry(v, _mfn(page_to_mfn(page)), pl1e);
|
||||
shadow2_unlock(v->domain);
|
||||
shadow_validate_guest_entry(v, _mfn(page_to_mfn(page)), pl1e);
|
||||
shadow_unlock(v->domain);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
subdir-y += shadow
|
||||
@@ -0,0 +1,15 @@
|
||||
ifneq ($(pae),n)
|
||||
obj-$(x86_32) += common.o g2_on_s3.o g3_on_s3.o
|
||||
else
|
||||
obj-$(x86_32) += common.o g2_on_s2.o
|
||||
endif
|
||||
|
||||
obj-$(x86_64) += common.o g4_on_s4.o g3_on_s3.o g2_on_s3.o
|
||||
|
||||
guest_levels = $(subst g,,$(filter g%,$(subst ., ,$(subst _, ,$(1)))))
|
||||
shadow_levels = $(subst s,,$(filter s%,$(subst ., ,$(subst _, ,$(1)))))
|
||||
shadow_defns = -DGUEST_PAGING_LEVELS=$(call guest_levels,$(1)) \
|
||||
-DSHADOW_PAGING_LEVELS=$(call shadow_levels,$(1))
|
||||
|
||||
g%.o: multi.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) $(call shadow_defns,$(@F)) -c $< -o $@
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
/******************************************************************************
|
||||
* arch/x86/shadow2-multi.h
|
||||
* arch/x86/mm/shadow/multi.h
|
||||
*
|
||||
* Shadow2 declarations which will be multiply compiled.
|
||||
* Shadow declarations which will 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.
|
||||
@@ -22,95 +22,95 @@
|
||||
*/
|
||||
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_map_and_validate_gl1e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_map_and_validate_gl1e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t gl1mfn, void *new_gl1p, u32 size);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_map_and_validate_gl2e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_map_and_validate_gl2e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t gl2mfn, void *new_gl2p, u32 size);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_map_and_validate_gl2he, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_map_and_validate_gl2he, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t gl2mfn, void *new_gl2p, u32 size);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_map_and_validate_gl3e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_map_and_validate_gl3e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t gl3mfn, void *new_gl3p, u32 size);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_map_and_validate_gl4e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_map_and_validate_gl4e, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t gl4mfn, void *new_gl4p, u32 size);
|
||||
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_l1_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t smfn);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_l2_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t smfn);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_l3_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_l3_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t smfn);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_l4_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_l4_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
|
||||
struct vcpu *v, mfn_t smfn);
|
||||
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_unpin_all_l3_subshadows, 3, 3)
|
||||
SHADOW_INTERNAL_NAME(sh_unpin_all_l3_subshadows, 3, 3)
|
||||
(struct vcpu *v, mfn_t smfn);
|
||||
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_unhook_32b_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_unhook_32b_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl2mfn);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_unhook_pae_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_unhook_pae_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl3mfn);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_unhook_64b_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_unhook_64b_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl4mfn);
|
||||
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_remove_write_access, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_remove_write_access, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl1mfn, mfn_t readonly_mfn);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_remove_all_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_remove_all_mappings, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl1mfn, mfn_t target_mfn);
|
||||
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_clear_shadow_entry, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_clear_shadow_entry, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, void *ep, mfn_t smfn);
|
||||
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_remove_l1_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_remove_l1_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl2mfn, mfn_t sl1mfn);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_remove_l2_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_remove_l2_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl3mfn, mfn_t sl2mfn);
|
||||
extern int
|
||||
SHADOW2_INTERNAL_NAME(sh2_remove_l3_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_remove_l3_shadow, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl4mfn, mfn_t sl3mfn);
|
||||
|
||||
#if SHADOW2_AUDIT & SHADOW2_AUDIT_ENTRIES
|
||||
#if SHADOW_AUDIT & SHADOW_AUDIT_ENTRIES
|
||||
int
|
||||
SHADOW2_INTERNAL_NAME(sh2_audit_l1_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_audit_l1_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl1mfn, mfn_t x);
|
||||
int
|
||||
SHADOW2_INTERNAL_NAME(sh2_audit_fl1_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_audit_fl1_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl1mfn, mfn_t x);
|
||||
int
|
||||
SHADOW2_INTERNAL_NAME(sh2_audit_l2_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_audit_l2_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl2mfn, mfn_t x);
|
||||
int
|
||||
SHADOW2_INTERNAL_NAME(sh2_audit_l3_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_audit_l3_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl3mfn, mfn_t x);
|
||||
int
|
||||
SHADOW2_INTERNAL_NAME(sh2_audit_l4_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_audit_l4_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t sl4mfn, mfn_t x);
|
||||
#endif
|
||||
|
||||
#if SHADOW_LEVELS == GUEST_LEVELS
|
||||
extern mfn_t
|
||||
SHADOW2_INTERNAL_NAME(sh2_make_monitor_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_make_monitor_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v);
|
||||
extern void
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_monitor_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_monitor_table, SHADOW_LEVELS, GUEST_LEVELS)
|
||||
(struct vcpu *v, mfn_t mmfn);
|
||||
#endif
|
||||
|
||||
extern struct shadow2_paging_mode
|
||||
SHADOW2_INTERNAL_NAME(sh2_paging_mode, SHADOW_LEVELS, GUEST_LEVELS);
|
||||
extern struct shadow_paging_mode
|
||||
SHADOW_INTERNAL_NAME(sh_paging_mode, SHADOW_LEVELS, GUEST_LEVELS);
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
/******************************************************************************
|
||||
* arch/x86/shadow2-private.h
|
||||
* arch/x86/mm/shadow/private.h
|
||||
*
|
||||
* Shadow2 code that is private, and does not need to be multiply compiled.
|
||||
* Shadow code that is private, and 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.
|
||||
@@ -21,8 +21,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _XEN_SHADOW2_PRIVATE_H
|
||||
#define _XEN_SHADOW2_PRIVATE_H
|
||||
#ifndef _XEN_SHADOW_PRIVATE_H
|
||||
#define _XEN_SHADOW_PRIVATE_H
|
||||
|
||||
// In order to override the definition of mfn_to_page, we make sure page.h has
|
||||
// been included...
|
||||
@@ -140,40 +140,40 @@
|
||||
/******************************************************************************
|
||||
* Debug and error-message output
|
||||
*/
|
||||
#define SHADOW2_PRINTK(_f, _a...) \
|
||||
debugtrace_printk("sh2: %s(): " _f, __func__, ##_a)
|
||||
#define SHADOW2_ERROR(_f, _a...) \
|
||||
printk("sh2 error: %s(): " _f, __func__, ##_a)
|
||||
#define SHADOW2_DEBUG(flag, _f, _a...) \
|
||||
#define SHADOW_PRINTK(_f, _a...) \
|
||||
debugtrace_printk("sh: %s(): " _f, __func__, ##_a)
|
||||
#define SHADOW_ERROR(_f, _a...) \
|
||||
printk("sh error: %s(): " _f, __func__, ##_a)
|
||||
#define SHADOW_DEBUG(flag, _f, _a...) \
|
||||
do { \
|
||||
if (SHADOW2_DEBUG_ ## flag) \
|
||||
debugtrace_printk("sh2debug: %s(): " _f, __func__, ##_a); \
|
||||
if (SHADOW_DEBUG_ ## flag) \
|
||||
debugtrace_printk("shdebug: %s(): " _f, __func__, ##_a); \
|
||||
} while (0)
|
||||
|
||||
// The flags for use with SHADOW2_DEBUG:
|
||||
#define SHADOW2_DEBUG_PROPAGATE 0
|
||||
#define SHADOW2_DEBUG_MAKE_SHADOW 0
|
||||
#define SHADOW2_DEBUG_DESTROY_SHADOW 0
|
||||
#define SHADOW2_DEBUG_P2M 0
|
||||
#define SHADOW2_DEBUG_A_AND_D 0
|
||||
#define SHADOW2_DEBUG_EMULATE 0
|
||||
#define SHADOW2_DEBUG_LOGDIRTY 1
|
||||
// The flags for use with SHADOW_DEBUG:
|
||||
#define SHADOW_DEBUG_PROPAGATE 0
|
||||
#define SHADOW_DEBUG_MAKE_SHADOW 0
|
||||
#define SHADOW_DEBUG_DESTROY_SHADOW 0
|
||||
#define SHADOW_DEBUG_P2M 0
|
||||
#define SHADOW_DEBUG_A_AND_D 0
|
||||
#define SHADOW_DEBUG_EMULATE 0
|
||||
#define SHADOW_DEBUG_LOGDIRTY 1
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Auditing routines
|
||||
*/
|
||||
|
||||
#if SHADOW2_AUDIT & SHADOW2_AUDIT_ENTRIES_FULL
|
||||
extern void shadow2_audit_tables(struct vcpu *v);
|
||||
#if SHADOW_AUDIT & SHADOW_AUDIT_ENTRIES_FULL
|
||||
extern void shadow_audit_tables(struct vcpu *v);
|
||||
#else
|
||||
#define shadow2_audit_tables(_v) do {} while(0)
|
||||
#define shadow_audit_tables(_v) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if SHADOW2_AUDIT & SHADOW2_AUDIT_P2M
|
||||
extern void shadow2_audit_p2m(struct domain *d);
|
||||
#if SHADOW_AUDIT & SHADOW_AUDIT_P2M
|
||||
extern void shadow_audit_p2m(struct domain *d);
|
||||
#else
|
||||
#define shadow2_audit_p2m(_d) do {} while(0)
|
||||
#define shadow_audit_p2m(_d) do {} while(0)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -185,82 +185,82 @@ extern void shadow2_audit_p2m(struct domain *d);
|
||||
* path fills in another. When the fault handler finishes, the
|
||||
* two are compared */
|
||||
|
||||
#ifdef SHADOW2_OPTIMIZATION_PARANOIA
|
||||
#ifdef SHADOW_OPTIMIZATION_PARANOIA
|
||||
|
||||
typedef struct shadow2_action_log sh2_log_t;
|
||||
struct shadow2_action_log {
|
||||
typedef struct shadow_action_log sh_log_t;
|
||||
struct shadow_action_log {
|
||||
paddr_t ad[CONFIG_PAGING_LEVELS]; /* A & D bits propagated here */
|
||||
paddr_t mmio; /* Address of an mmio operation */
|
||||
int rv; /* Result of the fault handler */
|
||||
};
|
||||
|
||||
/* There are two logs, one for the fast path, one for the normal path */
|
||||
enum sh2_log_type { log_slow = 0, log_fast= 1 };
|
||||
enum sh_log_type { log_slow = 0, log_fast= 1 };
|
||||
|
||||
/* Alloc and zero the logs */
|
||||
static inline void sh2_init_log(struct vcpu *v)
|
||||
static inline void sh_init_log(struct vcpu *v)
|
||||
{
|
||||
if ( unlikely(!v->arch.shadow2.action_log) )
|
||||
v->arch.shadow2.action_log = xmalloc_array(sh2_log_t, 2);
|
||||
ASSERT(v->arch.shadow2.action_log);
|
||||
memset(v->arch.shadow2.action_log, 0, 2 * sizeof (sh2_log_t));
|
||||
if ( unlikely(!v->arch.shadow.action_log) )
|
||||
v->arch.shadow.action_log = xmalloc_array(sh_log_t, 2);
|
||||
ASSERT(v->arch.shadow.action_log);
|
||||
memset(v->arch.shadow.action_log, 0, 2 * sizeof (sh_log_t));
|
||||
}
|
||||
|
||||
/* Log an A&D-bit update */
|
||||
static inline void sh2_log_ad(struct vcpu *v, paddr_t e, unsigned int level)
|
||||
static inline void sh_log_ad(struct vcpu *v, paddr_t e, unsigned int level)
|
||||
{
|
||||
v->arch.shadow2.action_log[v->arch.shadow2.action_index].ad[level] = e;
|
||||
v->arch.shadow.action_log[v->arch.shadow.action_index].ad[level] = e;
|
||||
}
|
||||
|
||||
/* Log an MMIO address */
|
||||
static inline void sh2_log_mmio(struct vcpu *v, paddr_t m)
|
||||
static inline void sh_log_mmio(struct vcpu *v, paddr_t m)
|
||||
{
|
||||
v->arch.shadow2.action_log[v->arch.shadow2.action_index].mmio = m;
|
||||
v->arch.shadow.action_log[v->arch.shadow.action_index].mmio = m;
|
||||
}
|
||||
|
||||
/* Log the result */
|
||||
static inline void sh2_log_rv(struct vcpu *v, int rv)
|
||||
static inline void sh_log_rv(struct vcpu *v, int rv)
|
||||
{
|
||||
v->arch.shadow2.action_log[v->arch.shadow2.action_index].rv = rv;
|
||||
v->arch.shadow.action_log[v->arch.shadow.action_index].rv = rv;
|
||||
}
|
||||
|
||||
/* Set which mode we're in */
|
||||
static inline void sh2_set_log_mode(struct vcpu *v, enum sh2_log_type t)
|
||||
static inline void sh_set_log_mode(struct vcpu *v, enum sh_log_type t)
|
||||
{
|
||||
v->arch.shadow2.action_index = t;
|
||||
v->arch.shadow.action_index = t;
|
||||
}
|
||||
|
||||
/* Know not to take action, because we're only checking the mechanism */
|
||||
static inline int sh2_take_no_action(struct vcpu *v)
|
||||
static inline int sh_take_no_action(struct vcpu *v)
|
||||
{
|
||||
return (v->arch.shadow2.action_index == log_fast);
|
||||
return (v->arch.shadow.action_index == log_fast);
|
||||
}
|
||||
|
||||
#else /* Non-paranoid mode: these logs do not exist */
|
||||
|
||||
#define sh2_init_log(_v) do { (void)(_v); } while(0)
|
||||
#define sh2_set_log_mode(_v,_t) do { (void)(_v); } while(0)
|
||||
#define sh2_log_ad(_v,_e,_l) do { (void)(_v),(void)(_e),(void)(_l); } while (0)
|
||||
#define sh2_log_mmio(_v,_m) do { (void)(_v),(void)(_m); } while (0)
|
||||
#define sh2_log_rv(_v,_r) do { (void)(_v),(void)(_r); } while (0)
|
||||
#define sh2_take_no_action(_v) (((void)(_v)), 0)
|
||||
#define sh_init_log(_v) do { (void)(_v); } while(0)
|
||||
#define sh_set_log_mode(_v,_t) do { (void)(_v); } while(0)
|
||||
#define sh_log_ad(_v,_e,_l) do { (void)(_v),(void)(_e),(void)(_l); } while (0)
|
||||
#define sh_log_mmio(_v,_m) do { (void)(_v),(void)(_m); } while (0)
|
||||
#define sh_log_rv(_v,_r) do { (void)(_v),(void)(_r); } while (0)
|
||||
#define sh_take_no_action(_v) (((void)(_v)), 0)
|
||||
|
||||
#endif /* SHADOW2_OPTIMIZATION_PARANOIA */
|
||||
#endif /* SHADOW_OPTIMIZATION_PARANOIA */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Macro for dealing with the naming of the internal names of the
|
||||
* shadow code's external entry points.
|
||||
*/
|
||||
#define SHADOW2_INTERNAL_NAME_HIDDEN(name, shadow_levels, guest_levels) \
|
||||
#define SHADOW_INTERNAL_NAME_HIDDEN(name, shadow_levels, guest_levels) \
|
||||
name ## __shadow_ ## shadow_levels ## _guest_ ## guest_levels
|
||||
#define SHADOW2_INTERNAL_NAME(name, shadow_levels, guest_levels) \
|
||||
SHADOW2_INTERNAL_NAME_HIDDEN(name, shadow_levels, guest_levels)
|
||||
#define SHADOW_INTERNAL_NAME(name, shadow_levels, guest_levels) \
|
||||
SHADOW_INTERNAL_NAME_HIDDEN(name, shadow_levels, guest_levels)
|
||||
|
||||
#if CONFIG_PAGING_LEVELS == 2
|
||||
#define GUEST_LEVELS 2
|
||||
#define SHADOW_LEVELS 2
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
#endif /* CONFIG_PAGING_LEVELS == 2 */
|
||||
@@ -268,13 +268,13 @@ static inline int sh2_take_no_action(struct vcpu *v)
|
||||
#if CONFIG_PAGING_LEVELS == 3
|
||||
#define GUEST_LEVELS 2
|
||||
#define SHADOW_LEVELS 3
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
|
||||
#define GUEST_LEVELS 3
|
||||
#define SHADOW_LEVELS 3
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
#endif /* CONFIG_PAGING_LEVELS == 3 */
|
||||
@@ -282,25 +282,25 @@ static inline int sh2_take_no_action(struct vcpu *v)
|
||||
#if CONFIG_PAGING_LEVELS == 4
|
||||
#define GUEST_LEVELS 2
|
||||
#define SHADOW_LEVELS 3
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
|
||||
#define GUEST_LEVELS 3
|
||||
#define SHADOW_LEVELS 3
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
|
||||
#define GUEST_LEVELS 3
|
||||
#define SHADOW_LEVELS 4
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
|
||||
#define GUEST_LEVELS 4
|
||||
#define SHADOW_LEVELS 4
|
||||
#include <asm/shadow2-multi.h>
|
||||
#include "multi.h"
|
||||
#undef GUEST_LEVELS
|
||||
#undef SHADOW_LEVELS
|
||||
#endif /* CONFIG_PAGING_LEVELS == 4 */
|
||||
@@ -311,39 +311,39 @@ static inline int sh2_take_no_action(struct vcpu *v)
|
||||
*/
|
||||
|
||||
/* x86 emulator support */
|
||||
extern struct x86_emulate_ops shadow2_emulator_ops;
|
||||
extern struct x86_emulate_ops shadow_emulator_ops;
|
||||
|
||||
/* Hash table functions */
|
||||
mfn_t shadow2_hash_lookup(struct vcpu *v, unsigned long n, u8 t);
|
||||
void shadow2_hash_insert(struct vcpu *v, unsigned long n, u8 t, mfn_t smfn);
|
||||
void shadow2_hash_delete(struct vcpu *v, unsigned long n, u8 t, mfn_t smfn);
|
||||
mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, u8 t);
|
||||
void shadow_hash_insert(struct vcpu *v, unsigned long n, u8 t, mfn_t smfn);
|
||||
void shadow_hash_delete(struct vcpu *v, unsigned long n, u8 t, mfn_t smfn);
|
||||
|
||||
/* shadow promotion */
|
||||
void shadow2_promote(struct vcpu *v, mfn_t gmfn, u32 type);
|
||||
void shadow2_demote(struct vcpu *v, mfn_t gmfn, u32 type);
|
||||
void shadow_promote(struct vcpu *v, mfn_t gmfn, u32 type);
|
||||
void shadow_demote(struct vcpu *v, mfn_t gmfn, u32 type);
|
||||
|
||||
/* Shadow page allocation functions */
|
||||
void shadow2_prealloc(struct domain *d, unsigned int order);
|
||||
mfn_t shadow2_alloc(struct domain *d,
|
||||
void shadow_prealloc(struct domain *d, unsigned int order);
|
||||
mfn_t shadow_alloc(struct domain *d,
|
||||
u32 shadow_type,
|
||||
unsigned long backpointer);
|
||||
void shadow2_free(struct domain *d, mfn_t smfn);
|
||||
void shadow_free(struct domain *d, mfn_t smfn);
|
||||
|
||||
/* Function to convert a shadow to log-dirty */
|
||||
void shadow2_convert_to_log_dirty(struct vcpu *v, mfn_t smfn);
|
||||
void shadow_convert_to_log_dirty(struct vcpu *v, mfn_t smfn);
|
||||
|
||||
/* Dispatcher function: call the per-mode function that will unhook the
|
||||
* non-Xen mappings in this top-level shadow mfn */
|
||||
void shadow2_unhook_mappings(struct vcpu *v, mfn_t smfn);
|
||||
void shadow_unhook_mappings(struct vcpu *v, mfn_t smfn);
|
||||
|
||||
/* Re-sync copies of PAE shadow L3 tables if they have been changed */
|
||||
void sh2_pae_recopy(struct domain *d);
|
||||
void sh_pae_recopy(struct domain *d);
|
||||
|
||||
/* Install the xen mappings in various flavours of shadow */
|
||||
void sh2_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn);
|
||||
void sh2_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn);
|
||||
void sh2_install_xen_entries_in_l3(struct vcpu *v, mfn_t gl3mfn, mfn_t sl3mfn);
|
||||
void sh2_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn);
|
||||
void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn);
|
||||
void sh_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn);
|
||||
void sh_install_xen_entries_in_l3(struct vcpu *v, mfn_t gl3mfn, mfn_t sl3mfn);
|
||||
void sh_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@@ -367,53 +367,53 @@ void sh2_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn);
|
||||
|
||||
// Provide mfn_t-aware versions of common xen functions
|
||||
static inline void *
|
||||
sh2_map_domain_page(mfn_t mfn)
|
||||
sh_map_domain_page(mfn_t mfn)
|
||||
{
|
||||
/* XXX Using the monitor-table as a map will happen here */
|
||||
return map_domain_page(mfn_x(mfn));
|
||||
}
|
||||
|
||||
static inline void
|
||||
sh2_unmap_domain_page(void *p)
|
||||
sh_unmap_domain_page(void *p)
|
||||
{
|
||||
/* XXX Using the monitor-table as a map will happen here */
|
||||
unmap_domain_page(p);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
sh2_map_domain_page_global(mfn_t mfn)
|
||||
sh_map_domain_page_global(mfn_t mfn)
|
||||
{
|
||||
/* XXX Using the monitor-table as a map will happen here */
|
||||
return map_domain_page_global(mfn_x(mfn));
|
||||
}
|
||||
|
||||
static inline void
|
||||
sh2_unmap_domain_page_global(void *p)
|
||||
sh_unmap_domain_page_global(void *p)
|
||||
{
|
||||
/* XXX Using the monitor-table as a map will happen here */
|
||||
unmap_domain_page_global(p);
|
||||
}
|
||||
|
||||
static inline int
|
||||
sh2_mfn_is_dirty(struct domain *d, mfn_t gmfn)
|
||||
sh_mfn_is_dirty(struct domain *d, mfn_t gmfn)
|
||||
/* Is this guest page dirty? Call only in log-dirty mode. */
|
||||
{
|
||||
unsigned long pfn;
|
||||
ASSERT(shadow2_mode_log_dirty(d));
|
||||
ASSERT(d->arch.shadow2.dirty_bitmap != NULL);
|
||||
ASSERT(shadow_mode_log_dirty(d));
|
||||
ASSERT(d->arch.shadow.dirty_bitmap != NULL);
|
||||
|
||||
/* We /really/ mean PFN here, even for non-translated guests. */
|
||||
pfn = get_gpfn_from_mfn(mfn_x(gmfn));
|
||||
if ( likely(VALID_M2P(pfn))
|
||||
&& likely(pfn < d->arch.shadow2.dirty_bitmap_size)
|
||||
&& test_bit(pfn, d->arch.shadow2.dirty_bitmap) )
|
||||
&& likely(pfn < d->arch.shadow.dirty_bitmap_size)
|
||||
&& test_bit(pfn, d->arch.shadow.dirty_bitmap) )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
sh2_mfn_is_a_page_table(mfn_t gmfn)
|
||||
sh_mfn_is_a_page_table(mfn_t gmfn)
|
||||
{
|
||||
struct page_info *page = mfn_to_page(gmfn);
|
||||
struct domain *owner;
|
||||
@@ -423,7 +423,7 @@ sh2_mfn_is_a_page_table(mfn_t gmfn)
|
||||
return 0;
|
||||
|
||||
owner = page_get_owner(page);
|
||||
if ( owner && shadow2_mode_refcounts(owner)
|
||||
if ( owner && shadow_mode_refcounts(owner)
|
||||
&& (page->count_info & PGC_page_table) )
|
||||
return 1;
|
||||
|
||||
@@ -433,33 +433,33 @@ sh2_mfn_is_a_page_table(mfn_t gmfn)
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Shadow-page refcounting. See comment in shadow2-common.c about the
|
||||
/* Shadow-page refcounting. See comment in shadow-common.c about the
|
||||
* use of struct page_info fields for shadow pages */
|
||||
|
||||
void sh2_destroy_shadow(struct vcpu *v, mfn_t smfn);
|
||||
void sh_destroy_shadow(struct vcpu *v, mfn_t smfn);
|
||||
|
||||
/* Increase the refcount of a shadow page. Arguments are the mfn to refcount,
|
||||
* and the physical address of the shadow entry that holds the ref (or zero
|
||||
* if the ref is held by something else) */
|
||||
static inline void sh2_get_ref(mfn_t smfn, paddr_t entry_pa)
|
||||
static inline void sh_get_ref(mfn_t smfn, paddr_t entry_pa)
|
||||
{
|
||||
u32 x, nx;
|
||||
struct page_info *page = mfn_to_page(smfn);
|
||||
|
||||
ASSERT(mfn_valid(smfn));
|
||||
|
||||
x = page->count_info & PGC_SH2_count_mask;
|
||||
x = page->count_info & PGC_SH_count_mask;
|
||||
nx = x + 1;
|
||||
|
||||
if ( unlikely(nx & ~PGC_SH2_count_mask) )
|
||||
if ( unlikely(nx & ~PGC_SH_count_mask) )
|
||||
{
|
||||
SHADOW2_PRINTK("shadow ref overflow, gmfn=%" PRtype_info " smfn=%lx\n",
|
||||
SHADOW_PRINTK("shadow ref overflow, gmfn=%" PRtype_info " smfn=%lx\n",
|
||||
page->u.inuse.type_info, mfn_x(smfn));
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
/* Guarded by the shadow lock, so no need for atomic update */
|
||||
page->count_info &= ~PGC_SH2_count_mask;
|
||||
page->count_info &= ~PGC_SH_count_mask;
|
||||
page->count_info |= nx;
|
||||
|
||||
/* We remember the first shadow entry that points to each shadow. */
|
||||
@@ -470,7 +470,7 @@ static inline void sh2_get_ref(mfn_t smfn, paddr_t entry_pa)
|
||||
|
||||
/* Decrease the refcount of a shadow page. As for get_ref, takes the
|
||||
* physical address of the shadow entry that held this reference. */
|
||||
static inline void sh2_put_ref(struct vcpu *v, mfn_t smfn, paddr_t entry_pa)
|
||||
static inline void sh_put_ref(struct vcpu *v, mfn_t smfn, paddr_t entry_pa)
|
||||
{
|
||||
u32 x, nx;
|
||||
struct page_info *page = mfn_to_page(smfn);
|
||||
@@ -482,53 +482,53 @@ static inline void sh2_put_ref(struct vcpu *v, mfn_t smfn, paddr_t entry_pa)
|
||||
if ( entry_pa != 0 && page->up == entry_pa )
|
||||
page->up = 0;
|
||||
|
||||
x = page->count_info & PGC_SH2_count_mask;
|
||||
x = page->count_info & PGC_SH_count_mask;
|
||||
nx = x - 1;
|
||||
|
||||
if ( unlikely(x == 0) )
|
||||
{
|
||||
SHADOW2_PRINTK("shadow ref underflow, smfn=%lx oc=%08x t=%"
|
||||
SHADOW_PRINTK("shadow ref underflow, smfn=%lx oc=%08x t=%"
|
||||
PRtype_info "\n",
|
||||
mfn_x(smfn),
|
||||
page->count_info & PGC_SH2_count_mask,
|
||||
page->count_info & PGC_SH_count_mask,
|
||||
page->u.inuse.type_info);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
/* Guarded by the shadow lock, so no need for atomic update */
|
||||
page->count_info &= ~PGC_SH2_count_mask;
|
||||
page->count_info &= ~PGC_SH_count_mask;
|
||||
page->count_info |= nx;
|
||||
|
||||
if ( unlikely(nx == 0) )
|
||||
sh2_destroy_shadow(v, smfn);
|
||||
sh_destroy_shadow(v, smfn);
|
||||
}
|
||||
|
||||
|
||||
/* Pin a shadow page: take an extra refcount and set the pin bit. */
|
||||
static inline void sh2_pin(mfn_t smfn)
|
||||
static inline void sh_pin(mfn_t smfn)
|
||||
{
|
||||
struct page_info *page;
|
||||
|
||||
ASSERT(mfn_valid(smfn));
|
||||
page = mfn_to_page(smfn);
|
||||
if ( !(page->count_info & PGC_SH2_pinned) )
|
||||
if ( !(page->count_info & PGC_SH_pinned) )
|
||||
{
|
||||
sh2_get_ref(smfn, 0);
|
||||
page->count_info |= PGC_SH2_pinned;
|
||||
sh_get_ref(smfn, 0);
|
||||
page->count_info |= PGC_SH_pinned;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unpin a shadow page: unset the pin bit and release the extra ref. */
|
||||
static inline void sh2_unpin(struct vcpu *v, mfn_t smfn)
|
||||
static inline void sh_unpin(struct vcpu *v, mfn_t smfn)
|
||||
{
|
||||
struct page_info *page;
|
||||
|
||||
ASSERT(mfn_valid(smfn));
|
||||
page = mfn_to_page(smfn);
|
||||
if ( page->count_info & PGC_SH2_pinned )
|
||||
if ( page->count_info & PGC_SH_pinned )
|
||||
{
|
||||
page->count_info &= ~PGC_SH2_pinned;
|
||||
sh2_put_ref(v, smfn, 0);
|
||||
page->count_info &= ~PGC_SH_pinned;
|
||||
sh_put_ref(v, smfn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +551,7 @@ vcpu_gfn_to_mfn_nofault(struct vcpu *v, unsigned long gfn)
|
||||
l1_pgentry_t *l1e;
|
||||
|
||||
ASSERT(current == v);
|
||||
if ( !shadow2_vcpu_mode_translate(v) )
|
||||
if ( !shadow_vcpu_mode_translate(v) )
|
||||
return _mfn(gfn);
|
||||
|
||||
#if CONFIG_PAGING_LEVELS > 2
|
||||
@@ -561,7 +561,7 @@ vcpu_gfn_to_mfn_nofault(struct vcpu *v, unsigned long gfn)
|
||||
#endif
|
||||
|
||||
/* Walk the linear pagetables. Note that this is *not* the same as
|
||||
* the walk in sh2_gfn_to_mfn_foreign, which is walking the p2m map */
|
||||
* the walk in sh_gfn_to_mfn_foreign, which is walking the p2m map */
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
l4e = __linear_l4_table + l4_linear_offset(entry_addr);
|
||||
if ( !(l4e_get_flags(*l4e) & _PAGE_PRESENT) ) return _mfn(INVALID_MFN);
|
||||
@@ -581,7 +581,7 @@ vcpu_gfn_to_mfn_nofault(struct vcpu *v, unsigned long gfn)
|
||||
}
|
||||
|
||||
|
||||
#endif /* _XEN_SHADOW2_PRIVATE_H */
|
||||
#endif /* _XEN_SHADOW_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* include/asm-x86/shadow2-types.h
|
||||
* arch/x86/mm/shadow/types.h
|
||||
*
|
||||
* Parts of this code are Copyright (c) 2006 by XenSource Inc.
|
||||
* Parts of this code are Copyright (c) 2006 by Michael A Fetterman
|
||||
@@ -20,8 +20,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _XEN_SHADOW2_TYPES_H
|
||||
#define _XEN_SHADOW2_TYPES_H
|
||||
#ifndef _XEN_SHADOW_TYPES_H
|
||||
#define _XEN_SHADOW_TYPES_H
|
||||
|
||||
// Map a shadow page
|
||||
static inline void *
|
||||
@@ -34,14 +34,14 @@ map_shadow_page(mfn_t smfn)
|
||||
// presumably using the reverse map hint in the page_info of this
|
||||
// smfn, rather than calling map_domain_page()?
|
||||
//
|
||||
return sh2_map_domain_page(smfn);
|
||||
return sh_map_domain_page(smfn);
|
||||
}
|
||||
|
||||
// matching unmap for map_shadow_page()
|
||||
static inline void
|
||||
unmap_shadow_page(void *p)
|
||||
{
|
||||
sh2_unmap_domain_page(p);
|
||||
sh_unmap_domain_page(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -188,52 +188,52 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t mfn, u32 flags)
|
||||
* guests, the shadow doesn't have a linear-map self-entry so we must use
|
||||
* the monitor-table's linear-map entry N-1 times and then the shadow-map
|
||||
* entry once. */
|
||||
#define __sh2_linear_l1_table ((shadow_l1e_t *)(SH_LINEAR_PT_VIRT_START))
|
||||
#define __sh2_linear_l2_table ((shadow_l2e_t *) \
|
||||
(__sh2_linear_l1_table + shadow_l1_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
#define __sh_linear_l1_table ((shadow_l1e_t *)(SH_LINEAR_PT_VIRT_START))
|
||||
#define __sh_linear_l2_table ((shadow_l2e_t *) \
|
||||
(__sh_linear_l1_table + shadow_l1_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
|
||||
// shadow linear L3 and L4 tables only exist in 4 level paging...
|
||||
#if SHADOW_PAGING_LEVELS == 4
|
||||
#define __sh2_linear_l3_table ((shadow_l3e_t *) \
|
||||
(__sh2_linear_l2_table + shadow_l2_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
#define __sh2_linear_l4_table ((shadow_l4e_t *) \
|
||||
(__sh2_linear_l3_table + shadow_l3_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
#define __sh_linear_l3_table ((shadow_l3e_t *) \
|
||||
(__sh_linear_l2_table + shadow_l2_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
#define __sh_linear_l4_table ((shadow_l4e_t *) \
|
||||
(__sh_linear_l3_table + shadow_l3_linear_offset(SH_LINEAR_PT_VIRT_START)))
|
||||
#endif
|
||||
|
||||
#define sh2_linear_l1_table(v) ({ \
|
||||
#define sh_linear_l1_table(v) ({ \
|
||||
ASSERT(current == (v)); \
|
||||
__sh2_linear_l1_table; \
|
||||
__sh_linear_l1_table; \
|
||||
})
|
||||
|
||||
#define sh2_linear_l2_table(v) ({ \
|
||||
#define sh_linear_l2_table(v) ({ \
|
||||
ASSERT(current == (v)); \
|
||||
((shadow_l2e_t *) \
|
||||
(hvm_guest(v) ? __linear_l1_table : __sh2_linear_l1_table) + \
|
||||
(hvm_guest(v) ? __linear_l1_table : __sh_linear_l1_table) + \
|
||||
shadow_l1_linear_offset(SH_LINEAR_PT_VIRT_START)); \
|
||||
})
|
||||
|
||||
// shadow linear L3 and L4 tables only exist in 4 level paging...
|
||||
#if SHADOW_PAGING_LEVELS == 4
|
||||
#define sh2_linear_l3_table(v) ({ \
|
||||
#define sh_linear_l3_table(v) ({ \
|
||||
ASSERT(current == (v)); \
|
||||
((shadow_l3e_t *) \
|
||||
(hvm_guest(v) ? __linear_l2_table : __sh2_linear_l2_table) + \
|
||||
(hvm_guest(v) ? __linear_l2_table : __sh_linear_l2_table) + \
|
||||
shadow_l2_linear_offset(SH_LINEAR_PT_VIRT_START)); \
|
||||
})
|
||||
|
||||
// we use l4_pgentry_t instead of shadow_l4e_t below because shadow_l4e_t is
|
||||
// not defined for when xen_levels==4 & shadow_levels==3...
|
||||
#define sh2_linear_l4_table(v) ({ \
|
||||
#define sh_linear_l4_table(v) ({ \
|
||||
ASSERT(current == (v)); \
|
||||
((l4_pgentry_t *) \
|
||||
(hvm_guest(v) ? __linear_l3_table : __sh2_linear_l3_table) + \
|
||||
(hvm_guest(v) ? __linear_l3_table : __sh_linear_l3_table) + \
|
||||
shadow_l3_linear_offset(SH_LINEAR_PT_VIRT_START)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if GUEST_PAGING_LEVELS == 2
|
||||
|
||||
#include <asm/page-guest32.h>
|
||||
#include "page-guest32.h"
|
||||
|
||||
#define GUEST_L1_PAGETABLE_ENTRIES 1024
|
||||
#define GUEST_L2_PAGETABLE_ENTRIES 1024
|
||||
@@ -243,7 +243,7 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t mfn, u32 flags)
|
||||
/* Type of the guest's frame numbers */
|
||||
TYPE_SAFE(u32,gfn)
|
||||
#define INVALID_GFN ((u32)(-1u))
|
||||
#define SH2_PRI_gfn "05x"
|
||||
#define SH_PRI_gfn "05x"
|
||||
|
||||
/* Types of the guest's page tables */
|
||||
typedef l1_pgentry_32_t guest_l1e_t;
|
||||
@@ -279,9 +279,9 @@ static inline guest_l2e_t guest_l2e_from_gfn(gfn_t gfn, u32 flags)
|
||||
#define guest_l2_table_offset(a) l2_table_offset_32(a)
|
||||
|
||||
/* The shadow types needed for the various levels. */
|
||||
#define PGC_SH2_l1_shadow PGC_SH2_l1_32_shadow
|
||||
#define PGC_SH2_l2_shadow PGC_SH2_l2_32_shadow
|
||||
#define PGC_SH2_fl1_shadow PGC_SH2_fl1_32_shadow
|
||||
#define PGC_SH_l1_shadow PGC_SH_l1_32_shadow
|
||||
#define PGC_SH_l2_shadow PGC_SH_l2_32_shadow
|
||||
#define PGC_SH_fl1_shadow PGC_SH_fl1_32_shadow
|
||||
|
||||
#else /* GUEST_PAGING_LEVELS != 2 */
|
||||
|
||||
@@ -306,7 +306,7 @@ static inline guest_l2e_t guest_l2e_from_gfn(gfn_t gfn, u32 flags)
|
||||
/* Type of the guest's frame numbers */
|
||||
TYPE_SAFE(unsigned long,gfn)
|
||||
#define INVALID_GFN ((unsigned long)(-1ul))
|
||||
#define SH2_PRI_gfn "05lx"
|
||||
#define SH_PRI_gfn "05lx"
|
||||
|
||||
/* Types of the guest's page tables */
|
||||
typedef l1_pgentry_t guest_l1e_t;
|
||||
@@ -379,17 +379,17 @@ static inline guest_l4e_t guest_l4e_from_gfn(gfn_t gfn, u32 flags)
|
||||
|
||||
/* The shadow types needed for the various levels. */
|
||||
#if GUEST_PAGING_LEVELS == 3
|
||||
#define PGC_SH2_l1_shadow PGC_SH2_l1_pae_shadow
|
||||
#define PGC_SH2_fl1_shadow PGC_SH2_fl1_pae_shadow
|
||||
#define PGC_SH2_l2_shadow PGC_SH2_l2_pae_shadow
|
||||
#define PGC_SH2_l2h_shadow PGC_SH2_l2h_pae_shadow
|
||||
#define PGC_SH2_l3_shadow PGC_SH2_l3_pae_shadow
|
||||
#define PGC_SH_l1_shadow PGC_SH_l1_pae_shadow
|
||||
#define PGC_SH_fl1_shadow PGC_SH_fl1_pae_shadow
|
||||
#define PGC_SH_l2_shadow PGC_SH_l2_pae_shadow
|
||||
#define PGC_SH_l2h_shadow PGC_SH_l2h_pae_shadow
|
||||
#define PGC_SH_l3_shadow PGC_SH_l3_pae_shadow
|
||||
#else
|
||||
#define PGC_SH2_l1_shadow PGC_SH2_l1_64_shadow
|
||||
#define PGC_SH2_fl1_shadow PGC_SH2_fl1_64_shadow
|
||||
#define PGC_SH2_l2_shadow PGC_SH2_l2_64_shadow
|
||||
#define PGC_SH2_l3_shadow PGC_SH2_l3_64_shadow
|
||||
#define PGC_SH2_l4_shadow PGC_SH2_l4_64_shadow
|
||||
#define PGC_SH_l1_shadow PGC_SH_l1_64_shadow
|
||||
#define PGC_SH_fl1_shadow PGC_SH_fl1_64_shadow
|
||||
#define PGC_SH_l2_shadow PGC_SH_l2_64_shadow
|
||||
#define PGC_SH_l3_shadow PGC_SH_l3_64_shadow
|
||||
#define PGC_SH_l4_shadow PGC_SH_l4_64_shadow
|
||||
#endif
|
||||
|
||||
#endif /* GUEST_PAGING_LEVELS != 2 */
|
||||
@@ -403,24 +403,24 @@ valid_gfn(gfn_t m)
|
||||
}
|
||||
|
||||
#if GUEST_PAGING_LEVELS == 2
|
||||
#define PGC_SH2_guest_root_type PGC_SH2_l2_32_shadow
|
||||
#define PGC_SH_guest_root_type PGC_SH_l2_32_shadow
|
||||
#elif GUEST_PAGING_LEVELS == 3
|
||||
#define PGC_SH2_guest_root_type PGC_SH2_l3_pae_shadow
|
||||
#define PGC_SH_guest_root_type PGC_SH_l3_pae_shadow
|
||||
#else
|
||||
#define PGC_SH2_guest_root_type PGC_SH2_l4_64_shadow
|
||||
#define PGC_SH_guest_root_type PGC_SH_l4_64_shadow
|
||||
#endif
|
||||
|
||||
/* Translation between mfns and gfns */
|
||||
static inline mfn_t
|
||||
vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn)
|
||||
{
|
||||
return sh2_vcpu_gfn_to_mfn(v, gfn_x(gfn));
|
||||
return sh_vcpu_gfn_to_mfn(v, gfn_x(gfn));
|
||||
}
|
||||
|
||||
static inline gfn_t
|
||||
mfn_to_gfn(struct domain *d, mfn_t mfn)
|
||||
{
|
||||
return _gfn(sh2_mfn_to_gfn(d, mfn));
|
||||
return _gfn(sh_mfn_to_gfn(d, mfn));
|
||||
}
|
||||
|
||||
static inline paddr_t
|
||||
@@ -438,8 +438,8 @@ gfn_to_paddr(gfn_t gfn)
|
||||
* The "Effective l1e" field is used when there isn't an l1e to point to,
|
||||
* but we have fabricated an l1e for propagation to the shadow (e.g.,
|
||||
* for splintering guest superpages into many shadow l1 entries). */
|
||||
typedef struct shadow2_walk_t walk_t;
|
||||
struct shadow2_walk_t
|
||||
typedef struct shadow_walk_t walk_t;
|
||||
struct shadow_walk_t
|
||||
{
|
||||
unsigned long va; /* Address we were looking for */
|
||||
#if GUEST_PAGING_LEVELS >= 3
|
||||
@@ -465,55 +465,55 @@ struct shadow2_walk_t
|
||||
* shadow code's external entry points.
|
||||
*/
|
||||
#define INTERNAL_NAME(name) \
|
||||
SHADOW2_INTERNAL_NAME(name, SHADOW_PAGING_LEVELS, GUEST_PAGING_LEVELS)
|
||||
SHADOW_INTERNAL_NAME(name, SHADOW_PAGING_LEVELS, GUEST_PAGING_LEVELS)
|
||||
|
||||
/* macros for renaming the primary entry points, so that they are more
|
||||
* easily distinguished from a debugger
|
||||
*/
|
||||
#define sh2_page_fault INTERNAL_NAME(sh2_page_fault)
|
||||
#define sh2_invlpg INTERNAL_NAME(sh2_invlpg)
|
||||
#define sh2_gva_to_gpa INTERNAL_NAME(sh2_gva_to_gpa)
|
||||
#define sh2_gva_to_gfn INTERNAL_NAME(sh2_gva_to_gfn)
|
||||
#define sh2_update_cr3 INTERNAL_NAME(sh2_update_cr3)
|
||||
#define sh2_remove_write_access INTERNAL_NAME(sh2_remove_write_access)
|
||||
#define sh2_remove_all_mappings INTERNAL_NAME(sh2_remove_all_mappings)
|
||||
#define sh2_remove_l1_shadow INTERNAL_NAME(sh2_remove_l1_shadow)
|
||||
#define sh2_remove_l2_shadow INTERNAL_NAME(sh2_remove_l2_shadow)
|
||||
#define sh2_remove_l3_shadow INTERNAL_NAME(sh2_remove_l3_shadow)
|
||||
#define sh2_map_and_validate_gl4e INTERNAL_NAME(sh2_map_and_validate_gl4e)
|
||||
#define sh2_map_and_validate_gl3e INTERNAL_NAME(sh2_map_and_validate_gl3e)
|
||||
#define sh2_map_and_validate_gl2e INTERNAL_NAME(sh2_map_and_validate_gl2e)
|
||||
#define sh2_map_and_validate_gl2he INTERNAL_NAME(sh2_map_and_validate_gl2he)
|
||||
#define sh2_map_and_validate_gl1e INTERNAL_NAME(sh2_map_and_validate_gl1e)
|
||||
#define sh2_destroy_l4_shadow INTERNAL_NAME(sh2_destroy_l4_shadow)
|
||||
#define sh2_destroy_l3_shadow INTERNAL_NAME(sh2_destroy_l3_shadow)
|
||||
#define sh2_destroy_l3_subshadow INTERNAL_NAME(sh2_destroy_l3_subshadow)
|
||||
#define sh2_unpin_all_l3_subshadows INTERNAL_NAME(sh2_unpin_all_l3_subshadows)
|
||||
#define sh2_destroy_l2_shadow INTERNAL_NAME(sh2_destroy_l2_shadow)
|
||||
#define sh2_destroy_l1_shadow INTERNAL_NAME(sh2_destroy_l1_shadow)
|
||||
#define sh2_unhook_32b_mappings INTERNAL_NAME(sh2_unhook_32b_mappings)
|
||||
#define sh2_unhook_pae_mappings INTERNAL_NAME(sh2_unhook_pae_mappings)
|
||||
#define sh2_unhook_64b_mappings INTERNAL_NAME(sh2_unhook_64b_mappings)
|
||||
#define sh2_paging_mode INTERNAL_NAME(sh2_paging_mode)
|
||||
#define sh2_detach_old_tables INTERNAL_NAME(sh2_detach_old_tables)
|
||||
#define sh2_x86_emulate_write INTERNAL_NAME(sh2_x86_emulate_write)
|
||||
#define sh2_x86_emulate_cmpxchg INTERNAL_NAME(sh2_x86_emulate_cmpxchg)
|
||||
#define sh2_x86_emulate_cmpxchg8b INTERNAL_NAME(sh2_x86_emulate_cmpxchg8b)
|
||||
#define sh2_audit_l1_table INTERNAL_NAME(sh2_audit_l1_table)
|
||||
#define sh2_audit_fl1_table INTERNAL_NAME(sh2_audit_fl1_table)
|
||||
#define sh2_audit_l2_table INTERNAL_NAME(sh2_audit_l2_table)
|
||||
#define sh2_audit_l3_table INTERNAL_NAME(sh2_audit_l3_table)
|
||||
#define sh2_audit_l4_table INTERNAL_NAME(sh2_audit_l4_table)
|
||||
#define sh2_guess_wrmap INTERNAL_NAME(sh2_guess_wrmap)
|
||||
#define sh2_clear_shadow_entry INTERNAL_NAME(sh2_clear_shadow_entry)
|
||||
#define sh_page_fault INTERNAL_NAME(sh_page_fault)
|
||||
#define sh_invlpg INTERNAL_NAME(sh_invlpg)
|
||||
#define sh_gva_to_gpa INTERNAL_NAME(sh_gva_to_gpa)
|
||||
#define sh_gva_to_gfn INTERNAL_NAME(sh_gva_to_gfn)
|
||||
#define sh_update_cr3 INTERNAL_NAME(sh_update_cr3)
|
||||
#define sh_remove_write_access INTERNAL_NAME(sh_remove_write_access)
|
||||
#define sh_remove_all_mappings INTERNAL_NAME(sh_remove_all_mappings)
|
||||
#define sh_remove_l1_shadow INTERNAL_NAME(sh_remove_l1_shadow)
|
||||
#define sh_remove_l2_shadow INTERNAL_NAME(sh_remove_l2_shadow)
|
||||
#define sh_remove_l3_shadow INTERNAL_NAME(sh_remove_l3_shadow)
|
||||
#define sh_map_and_validate_gl4e INTERNAL_NAME(sh_map_and_validate_gl4e)
|
||||
#define sh_map_and_validate_gl3e INTERNAL_NAME(sh_map_and_validate_gl3e)
|
||||
#define sh_map_and_validate_gl2e INTERNAL_NAME(sh_map_and_validate_gl2e)
|
||||
#define sh_map_and_validate_gl2he INTERNAL_NAME(sh_map_and_validate_gl2he)
|
||||
#define sh_map_and_validate_gl1e INTERNAL_NAME(sh_map_and_validate_gl1e)
|
||||
#define sh_destroy_l4_shadow INTERNAL_NAME(sh_destroy_l4_shadow)
|
||||
#define sh_destroy_l3_shadow INTERNAL_NAME(sh_destroy_l3_shadow)
|
||||
#define sh_destroy_l3_subshadow INTERNAL_NAME(sh_destroy_l3_subshadow)
|
||||
#define sh_unpin_all_l3_subshadows INTERNAL_NAME(sh_unpin_all_l3_subshadows)
|
||||
#define sh_destroy_l2_shadow INTERNAL_NAME(sh_destroy_l2_shadow)
|
||||
#define sh_destroy_l1_shadow INTERNAL_NAME(sh_destroy_l1_shadow)
|
||||
#define sh_unhook_32b_mappings INTERNAL_NAME(sh_unhook_32b_mappings)
|
||||
#define sh_unhook_pae_mappings INTERNAL_NAME(sh_unhook_pae_mappings)
|
||||
#define sh_unhook_64b_mappings INTERNAL_NAME(sh_unhook_64b_mappings)
|
||||
#define sh_paging_mode INTERNAL_NAME(sh_paging_mode)
|
||||
#define sh_detach_old_tables INTERNAL_NAME(sh_detach_old_tables)
|
||||
#define sh_x86_emulate_write INTERNAL_NAME(sh_x86_emulate_write)
|
||||
#define sh_x86_emulate_cmpxchg INTERNAL_NAME(sh_x86_emulate_cmpxchg)
|
||||
#define sh_x86_emulate_cmpxchg8b INTERNAL_NAME(sh_x86_emulate_cmpxchg8b)
|
||||
#define sh_audit_l1_table INTERNAL_NAME(sh_audit_l1_table)
|
||||
#define sh_audit_fl1_table INTERNAL_NAME(sh_audit_fl1_table)
|
||||
#define sh_audit_l2_table INTERNAL_NAME(sh_audit_l2_table)
|
||||
#define sh_audit_l3_table INTERNAL_NAME(sh_audit_l3_table)
|
||||
#define sh_audit_l4_table INTERNAL_NAME(sh_audit_l4_table)
|
||||
#define sh_guess_wrmap INTERNAL_NAME(sh_guess_wrmap)
|
||||
#define sh_clear_shadow_entry INTERNAL_NAME(sh_clear_shadow_entry)
|
||||
|
||||
/* sh2_make_monitor_table only depends on the number of shadow levels */
|
||||
#define sh2_make_monitor_table \
|
||||
SHADOW2_INTERNAL_NAME(sh2_make_monitor_table, \
|
||||
/* sh_make_monitor_table only depends on the number of shadow levels */
|
||||
#define sh_make_monitor_table \
|
||||
SHADOW_INTERNAL_NAME(sh_make_monitor_table, \
|
||||
SHADOW_PAGING_LEVELS, \
|
||||
SHADOW_PAGING_LEVELS)
|
||||
#define sh2_destroy_monitor_table \
|
||||
SHADOW2_INTERNAL_NAME(sh2_destroy_monitor_table, \
|
||||
#define sh_destroy_monitor_table \
|
||||
SHADOW_INTERNAL_NAME(sh_destroy_monitor_table, \
|
||||
SHADOW_PAGING_LEVELS, \
|
||||
SHADOW_PAGING_LEVELS)
|
||||
|
||||
@@ -537,22 +537,22 @@ struct pae_l3_bookkeeping {
|
||||
#define sl3p_to_info(_ptr) ((struct pae_l3_bookkeeping *) \
|
||||
(((unsigned long)(_ptr) & ~31) + 32))
|
||||
|
||||
static void sh2_destroy_l3_subshadow(struct vcpu *v,
|
||||
static void sh_destroy_l3_subshadow(struct vcpu *v,
|
||||
shadow_l3e_t *sl3e);
|
||||
|
||||
/* Increment a subshadow ref
|
||||
* Called with a pointer to the subshadow, and the mfn of the
|
||||
* *first* page of the overall shadow. */
|
||||
static inline void sh2_get_ref_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
static inline void sh_get_ref_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
{
|
||||
struct pae_l3_bookkeeping *bk = sl3p_to_info(sl3e);
|
||||
|
||||
/* First ref to the subshadow takes a ref to the full shadow */
|
||||
if ( bk->refcount == 0 )
|
||||
sh2_get_ref(smfn, 0);
|
||||
sh_get_ref(smfn, 0);
|
||||
if ( unlikely(++(bk->refcount) == 0) )
|
||||
{
|
||||
SHADOW2_PRINTK("shadow l3 subshadow ref overflow, smfn=%" SH2_PRI_mfn " sh=%p\n",
|
||||
SHADOW_PRINTK("shadow l3 subshadow ref overflow, smfn=%" SH_PRI_mfn " sh=%p\n",
|
||||
mfn_x(smfn), sl3e);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
@@ -563,7 +563,7 @@ static inline void sh2_get_ref_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
* *first* page of the overall shadow. Calling this may cause the
|
||||
* entire shadow to disappear, so the caller must immediately unmap
|
||||
* the pointer after calling. */
|
||||
static inline void sh2_put_ref_l3_subshadow(struct vcpu *v,
|
||||
static inline void sh_put_ref_l3_subshadow(struct vcpu *v,
|
||||
shadow_l3e_t *sl3e,
|
||||
mfn_t smfn)
|
||||
{
|
||||
@@ -575,16 +575,16 @@ static inline void sh2_put_ref_l3_subshadow(struct vcpu *v,
|
||||
if ( --(bk->refcount) == 0 )
|
||||
{
|
||||
/* Need to destroy this subshadow */
|
||||
sh2_destroy_l3_subshadow(v, sl3e);
|
||||
sh_destroy_l3_subshadow(v, sl3e);
|
||||
/* Last ref to the subshadow had a ref to the full shadow */
|
||||
sh2_put_ref(v, smfn, 0);
|
||||
sh_put_ref(v, smfn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pin a subshadow
|
||||
* Called with a pointer to the subshadow, and the mfn of the
|
||||
* *first* page of the overall shadow. */
|
||||
static inline void sh2_pin_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
static inline void sh_pin_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
{
|
||||
struct pae_l3_bookkeeping *bk = sl3p_to_info(sl3e);
|
||||
|
||||
@@ -597,7 +597,7 @@ static inline void sh2_pin_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
if ( !bk->pinned )
|
||||
{
|
||||
bk->pinned = 1;
|
||||
sh2_get_ref_l3_subshadow(sl3e, smfn);
|
||||
sh_get_ref_l3_subshadow(sl3e, smfn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ static inline void sh2_pin_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
|
||||
* *first* page of the overall shadow. Calling this may cause the
|
||||
* entire shadow to disappear, so the caller must immediately unmap
|
||||
* the pointer after calling. */
|
||||
static inline void sh2_unpin_l3_subshadow(struct vcpu *v,
|
||||
static inline void sh_unpin_l3_subshadow(struct vcpu *v,
|
||||
shadow_l3e_t *sl3e,
|
||||
mfn_t smfn)
|
||||
{
|
||||
@@ -621,7 +621,7 @@ static inline void sh2_unpin_l3_subshadow(struct vcpu *v,
|
||||
if ( bk->pinned )
|
||||
{
|
||||
bk->pinned = 0;
|
||||
sh2_put_ref_l3_subshadow(v, sl3e, smfn);
|
||||
sh_put_ref_l3_subshadow(v, sl3e, smfn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,22 +632,22 @@ static inline void sh2_unpin_l3_subshadow(struct vcpu *v,
|
||||
#endif
|
||||
|
||||
#if SHADOW_PAGING_LEVELS == 2
|
||||
#define SH2_PRI_pte "08x"
|
||||
#define SH_PRI_pte "08x"
|
||||
#else /* SHADOW_PAGING_LEVELS >= 3 */
|
||||
#ifndef __x86_64__
|
||||
#define SH2_PRI_pte "016llx"
|
||||
#define SH_PRI_pte "016llx"
|
||||
#else
|
||||
#define SH2_PRI_pte "016lx"
|
||||
#define SH_PRI_pte "016lx"
|
||||
#endif
|
||||
#endif /* SHADOW_PAGING_LEVELS >= 3 */
|
||||
|
||||
#if GUEST_PAGING_LEVELS == 2
|
||||
#define SH2_PRI_gpte "08x"
|
||||
#define SH_PRI_gpte "08x"
|
||||
#else /* GUEST_PAGING_LEVELS >= 3 */
|
||||
#ifndef __x86_64__
|
||||
#define SH2_PRI_gpte "016llx"
|
||||
#define SH_PRI_gpte "016llx"
|
||||
#else
|
||||
#define SH2_PRI_gpte "016lx"
|
||||
#define SH_PRI_gpte "016lx"
|
||||
#endif
|
||||
#endif /* GUEST_PAGING_LEVELS >= 3 */
|
||||
|
||||
@@ -680,7 +680,7 @@ accumulate_guest_flags(walk_t *gw)
|
||||
return accumulated_flags;
|
||||
}
|
||||
|
||||
#endif /* _XEN_SHADOW2_TYPES_H */
|
||||
#endif /* _XEN_SHADOW_TYPES_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
@@ -870,8 +870,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
|
||||
|
||||
if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
|
||||
{
|
||||
if ( shadow2_mode_external(d) && guest_mode(regs) )
|
||||
return shadow2_fault(addr, regs);
|
||||
if ( shadow_mode_external(d) && guest_mode(regs) )
|
||||
return shadow_fault(addr, regs);
|
||||
if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) )
|
||||
return handle_gdt_ldt_mapping_fault(
|
||||
addr - GDT_LDT_VIRT_START, regs);
|
||||
@@ -890,8 +890,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
|
||||
ptwr_do_page_fault(d, addr, regs) )
|
||||
return EXCRET_fault_fixed;
|
||||
|
||||
if ( shadow2_mode_enabled(d) )
|
||||
return shadow2_fault(addr, regs);
|
||||
if ( shadow_mode_enabled(d) )
|
||||
return shadow_fault(addr, regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ extern void hypercall_page_initialise(struct domain *d, void *);
|
||||
|
||||
struct shadow_domain {
|
||||
u32 mode; /* flags to control shadow operation */
|
||||
spinlock_t lock; /* shadow2 domain lock */
|
||||
spinlock_t lock; /* shadow domain lock */
|
||||
int locker; /* processor which holds the lock */
|
||||
const char *locker_function; /* Func that took it */
|
||||
struct list_head freelists[SHADOW2_MAX_ORDER + 1];
|
||||
struct list_head freelists[SHADOW_MAX_ORDER + 1];
|
||||
struct list_head p2m_freelist;
|
||||
struct list_head p2m_inuse;
|
||||
struct list_head toplevel_shadows;
|
||||
@@ -70,10 +70,10 @@ struct shadow_domain {
|
||||
unsigned int free_pages; /* number of pages on freelists */
|
||||
unsigned int p2m_pages; /* number of pages in p2m map */
|
||||
|
||||
/* Shadow2 hashtable */
|
||||
struct shadow2_hash_entry *hash_table;
|
||||
struct shadow2_hash_entry *hash_freelist;
|
||||
struct shadow2_hash_entry *hash_allocations;
|
||||
/* Shadow hashtable */
|
||||
struct shadow_hash_entry *hash_table;
|
||||
struct shadow_hash_entry *hash_freelist;
|
||||
struct shadow_hash_entry *hash_allocations;
|
||||
int hash_walking; /* Some function is walking the hash table */
|
||||
|
||||
/* Shadow log-dirty bitmap */
|
||||
@@ -107,7 +107,7 @@ struct arch_domain
|
||||
/* Shadow-translated guest: Pseudophys base address of reserved area. */
|
||||
unsigned long first_reserved_pfn;
|
||||
|
||||
struct shadow_domain shadow2;
|
||||
struct shadow_domain shadow;
|
||||
|
||||
/* Shadow translated domain: P2M mapping */
|
||||
pagetable_t phys_table;
|
||||
@@ -135,7 +135,7 @@ struct pae_l3_cache { };
|
||||
|
||||
struct shadow_vcpu {
|
||||
/* Pointers to mode-specific entry points. */
|
||||
struct shadow2_paging_mode *mode;
|
||||
struct shadow_paging_mode *mode;
|
||||
/* Last MFN that we emulated a write to. */
|
||||
unsigned long last_emulated_mfn;
|
||||
/* HVM guest: paging enabled (CR0.PG)? */
|
||||
@@ -201,7 +201,7 @@ struct arch_vcpu
|
||||
/* Current LDT details. */
|
||||
unsigned long shadow_ldt_mapcnt;
|
||||
|
||||
struct shadow_vcpu shadow2;
|
||||
struct shadow_vcpu shadow;
|
||||
} __cacheline_aligned;
|
||||
|
||||
/* shorthands to improve code legibility */
|
||||
|
||||
+38
-38
@@ -22,7 +22,7 @@ struct page_info
|
||||
/* Each frame can be threaded onto a doubly-linked list. */
|
||||
union {
|
||||
struct list_head list;
|
||||
/* Shadow2 uses this field as an up-pointer in lower-level shadows */
|
||||
/* Shadow uses this field as an up-pointer in lower-level shadows */
|
||||
paddr_t up;
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ struct page_info
|
||||
/* Only used on guest pages with a shadow.
|
||||
* Guest pages with a shadow must have a non-zero type count, so this
|
||||
* does not conflict with the tlbflush timestamp. */
|
||||
u32 shadow2_flags;
|
||||
u32 shadow_flags;
|
||||
|
||||
// XXX -- we expect to add another field here, to be used for min/max
|
||||
// purposes, which is only used for shadow pages.
|
||||
@@ -76,7 +76,7 @@ struct page_info
|
||||
#define PGT_ldt_page (6U<<29) /* using this page in an LDT? */
|
||||
#define PGT_writable_page (7U<<29) /* has writable mappings of this page? */
|
||||
|
||||
#ifndef SHADOW2
|
||||
#ifndef SHADOW
|
||||
#define PGT_l1_shadow PGT_l1_page_table
|
||||
#define PGT_l2_shadow PGT_l2_page_table
|
||||
#define PGT_l3_shadow PGT_l3_page_table
|
||||
@@ -117,7 +117,7 @@ struct page_info
|
||||
/* 16-bit count of uses of this frame as its current type. */
|
||||
#define PGT_count_mask ((1U<<16)-1)
|
||||
|
||||
#ifndef SHADOW2
|
||||
#ifndef SHADOW
|
||||
#ifdef __x86_64__
|
||||
#define PGT_high_mfn_shift 52
|
||||
#define PGT_high_mfn_mask (0xfffUL << PGT_high_mfn_shift)
|
||||
@@ -132,7 +132,7 @@ struct page_info
|
||||
#define PGT_score_shift 23
|
||||
#define PGT_score_mask (((1U<<4)-1)<<PGT_score_shift)
|
||||
#endif
|
||||
#endif /* SHADOW2 */
|
||||
#endif /* SHADOW */
|
||||
|
||||
/* Cleared when the owning guest 'frees' this page. */
|
||||
#define _PGC_allocated 31
|
||||
@@ -146,38 +146,38 @@ struct page_info
|
||||
/* 29-bit count of references to this frame. */
|
||||
#define PGC_count_mask ((1U<<29)-1)
|
||||
|
||||
/* shadow2 uses the count_info on shadow pages somewhat differently */
|
||||
/* NB: please coordinate any changes here with the SH2F's in shadow2.h */
|
||||
#define PGC_SH2_none (0U<<28) /* on the shadow2 free list */
|
||||
#define PGC_SH2_min_shadow (1U<<28)
|
||||
#define PGC_SH2_l1_32_shadow (1U<<28) /* shadowing a 32-bit L1 guest page */
|
||||
#define PGC_SH2_fl1_32_shadow (2U<<28) /* L1 shadow for a 32b 4M superpage */
|
||||
#define PGC_SH2_l2_32_shadow (3U<<28) /* shadowing a 32-bit L2 guest page */
|
||||
#define PGC_SH2_l1_pae_shadow (4U<<28) /* shadowing a pae L1 page */
|
||||
#define PGC_SH2_fl1_pae_shadow (5U<<28) /* L1 shadow for pae 2M superpg */
|
||||
#define PGC_SH2_l2_pae_shadow (6U<<28) /* shadowing a pae L2-low page */
|
||||
#define PGC_SH2_l2h_pae_shadow (7U<<28) /* shadowing a pae L2-high page */
|
||||
#define PGC_SH2_l3_pae_shadow (8U<<28) /* shadowing a pae L3 page */
|
||||
#define PGC_SH2_l1_64_shadow (9U<<28) /* shadowing a 64-bit L1 page */
|
||||
#define PGC_SH2_fl1_64_shadow (10U<<28) /* L1 shadow for 64-bit 2M superpg */
|
||||
#define PGC_SH2_l2_64_shadow (11U<<28) /* shadowing a 64-bit L2 page */
|
||||
#define PGC_SH2_l3_64_shadow (12U<<28) /* shadowing a 64-bit L3 page */
|
||||
#define PGC_SH2_l4_64_shadow (13U<<28) /* shadowing a 64-bit L4 page */
|
||||
#define PGC_SH2_max_shadow (13U<<28)
|
||||
#define PGC_SH2_p2m_table (14U<<28) /* in use as the p2m table */
|
||||
#define PGC_SH2_monitor_table (15U<<28) /* in use as a monitor table */
|
||||
#define PGC_SH2_unused (15U<<28)
|
||||
/* shadow uses the count_info on shadow pages somewhat differently */
|
||||
/* NB: please coordinate any changes here with the SHF's in shadow.h */
|
||||
#define PGC_SH_none (0U<<28) /* on the shadow free list */
|
||||
#define PGC_SH_min_shadow (1U<<28)
|
||||
#define PGC_SH_l1_32_shadow (1U<<28) /* shadowing a 32-bit L1 guest page */
|
||||
#define PGC_SH_fl1_32_shadow (2U<<28) /* L1 shadow for a 32b 4M superpage */
|
||||
#define PGC_SH_l2_32_shadow (3U<<28) /* shadowing a 32-bit L2 guest page */
|
||||
#define PGC_SH_l1_pae_shadow (4U<<28) /* shadowing a pae L1 page */
|
||||
#define PGC_SH_fl1_pae_shadow (5U<<28) /* L1 shadow for pae 2M superpg */
|
||||
#define PGC_SH_l2_pae_shadow (6U<<28) /* shadowing a pae L2-low page */
|
||||
#define PGC_SH_l2h_pae_shadow (7U<<28) /* shadowing a pae L2-high page */
|
||||
#define PGC_SH_l3_pae_shadow (8U<<28) /* shadowing a pae L3 page */
|
||||
#define PGC_SH_l1_64_shadow (9U<<28) /* shadowing a 64-bit L1 page */
|
||||
#define PGC_SH_fl1_64_shadow (10U<<28) /* L1 shadow for 64-bit 2M superpg */
|
||||
#define PGC_SH_l2_64_shadow (11U<<28) /* shadowing a 64-bit L2 page */
|
||||
#define PGC_SH_l3_64_shadow (12U<<28) /* shadowing a 64-bit L3 page */
|
||||
#define PGC_SH_l4_64_shadow (13U<<28) /* shadowing a 64-bit L4 page */
|
||||
#define PGC_SH_max_shadow (13U<<28)
|
||||
#define PGC_SH_p2m_table (14U<<28) /* in use as the p2m table */
|
||||
#define PGC_SH_monitor_table (15U<<28) /* in use as a monitor table */
|
||||
#define PGC_SH_unused (15U<<28)
|
||||
|
||||
#define PGC_SH2_type_mask (15U<<28)
|
||||
#define PGC_SH2_type_shift 28
|
||||
#define PGC_SH_type_mask (15U<<28)
|
||||
#define PGC_SH_type_shift 28
|
||||
|
||||
#define PGC_SH2_pinned (1U<<27)
|
||||
#define PGC_SH_pinned (1U<<27)
|
||||
|
||||
#define _PGC_SH2_log_dirty 26
|
||||
#define PGC_SH2_log_dirty (1U<<26)
|
||||
#define _PGC_SH_log_dirty 26
|
||||
#define PGC_SH_log_dirty (1U<<26)
|
||||
|
||||
/* 26 bit ref count for shadow pages */
|
||||
#define PGC_SH2_count_mask ((1U<<26) - 1)
|
||||
#define PGC_SH_count_mask ((1U<<26) - 1)
|
||||
|
||||
/* We trust the slab allocator in slab.c, and our use of it. */
|
||||
#define PageSlab(page) (1)
|
||||
@@ -201,9 +201,9 @@ static inline u32 pickle_domptr(struct domain *domain)
|
||||
|
||||
/* The order of the largest allocation unit we use for shadow pages */
|
||||
#if CONFIG_PAGING_LEVELS == 2
|
||||
#define SHADOW2_MAX_ORDER 0 /* Only ever need 4k allocations */
|
||||
#define SHADOW_MAX_ORDER 0 /* Only ever need 4k allocations */
|
||||
#else
|
||||
#define SHADOW2_MAX_ORDER 2 /* Need up to 16k allocs for 32-bit on PAE/64 */
|
||||
#define SHADOW_MAX_ORDER 2 /* Need up to 16k allocs for 32-bit on PAE/64 */
|
||||
#endif
|
||||
|
||||
#define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
|
||||
@@ -227,7 +227,7 @@ extern void invalidate_shadow_ldt(struct vcpu *d);
|
||||
extern int shadow_remove_all_write_access(
|
||||
struct domain *d, unsigned long gmfn, unsigned long mfn);
|
||||
extern u32 shadow_remove_all_access( struct domain *d, unsigned long gmfn);
|
||||
extern int _shadow2_mode_refcounts(struct domain *d);
|
||||
extern int _shadow_mode_refcounts(struct domain *d);
|
||||
|
||||
static inline void put_page(struct page_info *page)
|
||||
{
|
||||
@@ -259,7 +259,7 @@ static inline int get_page(struct page_info *page,
|
||||
unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
|
||||
unlikely(d != _domain) ) /* Wrong owner? */
|
||||
{
|
||||
if ( !_shadow2_mode_refcounts(domain) )
|
||||
if ( !_shadow_mode_refcounts(domain) )
|
||||
DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%"
|
||||
PRtype_info "\n",
|
||||
page_to_mfn(page), domain, unpickle_domptr(d),
|
||||
@@ -345,11 +345,11 @@ int check_descriptor(struct desc_struct *d);
|
||||
|
||||
|
||||
#define mfn_to_gmfn(_d, mfn) \
|
||||
( (shadow2_mode_translate(_d)) \
|
||||
( (shadow_mode_translate(_d)) \
|
||||
? get_gpfn_from_mfn(mfn) \
|
||||
: (mfn) )
|
||||
|
||||
#define gmfn_to_mfn(_d, gpfn) mfn_x(sh2_gfn_to_mfn(_d, gpfn))
|
||||
#define gmfn_to_mfn(_d, gpfn) mfn_x(sh_gfn_to_mfn(_d, gpfn))
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -30,59 +30,59 @@ PERFCOUNTER_CPU(ptwr_emulations, "writable pt emulations")
|
||||
PERFCOUNTER_CPU(exception_fixed, "pre-exception fixed")
|
||||
|
||||
|
||||
/* Shadow2 counters */
|
||||
PERFCOUNTER_CPU(shadow2_alloc, "calls to shadow2_alloc")
|
||||
PERFCOUNTER_CPU(shadow2_alloc_tlbflush, "shadow2_alloc flushed TLBs")
|
||||
/* Shadow counters */
|
||||
PERFCOUNTER_CPU(shadow_alloc, "calls to shadow_alloc")
|
||||
PERFCOUNTER_CPU(shadow_alloc_tlbflush, "shadow_alloc flushed TLBs")
|
||||
|
||||
/* STATUS counters do not reset when 'P' is hit */
|
||||
PERFSTATUS(shadow2_alloc_count, "number of shadow pages in use")
|
||||
PERFCOUNTER_CPU(shadow2_free, "calls to shadow2_free")
|
||||
PERFCOUNTER_CPU(shadow2_prealloc_1, "shadow2 recycles old shadows")
|
||||
PERFCOUNTER_CPU(shadow2_prealloc_2, "shadow2 recycles in-use shadows")
|
||||
PERFCOUNTER_CPU(shadow2_linear_map_failed, "shadow2 hit read-only linear map")
|
||||
PERFCOUNTER_CPU(shadow2_a_update, "shadow2 A bit update")
|
||||
PERFCOUNTER_CPU(shadow2_ad_update, "shadow2 A&D bit update")
|
||||
PERFCOUNTER_CPU(shadow2_fault, "calls to shadow2_fault")
|
||||
PERFCOUNTER_CPU(shadow2_fault_bail_bad_gfn, "shadow2_fault guest bad gfn")
|
||||
PERFCOUNTER_CPU(shadow2_fault_bail_not_present,
|
||||
"shadow2_fault guest not-present")
|
||||
PERFCOUNTER_CPU(shadow2_fault_bail_nx, "shadow2_fault guest NX fault")
|
||||
PERFCOUNTER_CPU(shadow2_fault_bail_ro_mapping, "shadow2_fault guest R/W fault")
|
||||
PERFCOUNTER_CPU(shadow2_fault_bail_user_supervisor,
|
||||
"shadow2_fault guest U/S fault")
|
||||
PERFCOUNTER_CPU(shadow2_fault_emulate_read, "shadow2_fault emulates a read")
|
||||
PERFCOUNTER_CPU(shadow2_fault_emulate_write, "shadow2_fault emulates a write")
|
||||
PERFCOUNTER_CPU(shadow2_fault_emulate_failed, "shadow2_fault emulator fails")
|
||||
PERFCOUNTER_CPU(shadow2_fault_mmio, "shadow2_fault handled as mmio")
|
||||
PERFCOUNTER_CPU(shadow2_fault_fixed, "shadow2_fault fixed fault")
|
||||
PERFCOUNTER_CPU(shadow2_ptwr_emulate, "shadow2 causes ptwr to emulate")
|
||||
PERFCOUNTER_CPU(shadow2_validate_gl1e_calls, "calls to shadow2_validate_gl1e")
|
||||
PERFCOUNTER_CPU(shadow2_validate_gl2e_calls, "calls to shadow2_validate_gl2e")
|
||||
PERFCOUNTER_CPU(shadow2_validate_gl3e_calls, "calls to shadow2_validate_gl3e")
|
||||
PERFCOUNTER_CPU(shadow2_validate_gl4e_calls, "calls to shadow2_validate_gl4e")
|
||||
PERFCOUNTER_CPU(shadow2_hash_lookups, "calls to shadow2_hash_lookup")
|
||||
PERFCOUNTER_CPU(shadow2_hash_lookup_head, "shadow2 hash hit in bucket head")
|
||||
PERFCOUNTER_CPU(shadow2_hash_lookup_miss, "shadow2 hash misses")
|
||||
PERFCOUNTER_CPU(shadow2_get_shadow_status, "calls to get_shadow_status")
|
||||
PERFCOUNTER_CPU(shadow2_hash_inserts, "calls to shadow2_hash_insert")
|
||||
PERFCOUNTER_CPU(shadow2_hash_deletes, "calls to shadow2_hash_delete")
|
||||
PERFCOUNTER_CPU(shadow2_writeable, "shadow2 removes write access")
|
||||
PERFCOUNTER_CPU(shadow2_writeable_h_1, "shadow2 writeable: 32b w2k3")
|
||||
PERFCOUNTER_CPU(shadow2_writeable_h_2, "shadow2 writeable: 32pae w2k3")
|
||||
PERFCOUNTER_CPU(shadow2_writeable_h_3, "shadow2 writeable: 64b w2k3")
|
||||
PERFCOUNTER_CPU(shadow2_writeable_h_4, "shadow2 writeable: 32b linux low")
|
||||
PERFCOUNTER_CPU(shadow2_writeable_bf, "shadow2 writeable brute-force")
|
||||
PERFCOUNTER_CPU(shadow2_mappings, "shadow2 removes all mappings")
|
||||
PERFCOUNTER_CPU(shadow2_mappings_bf, "shadow2 rm-mappings brute-force")
|
||||
PERFCOUNTER_CPU(shadow2_early_unshadow, "shadow2 unshadows for fork/exit")
|
||||
PERFCOUNTER_CPU(shadow2_early_unshadow_top, "shadow2 unhooks for fork/exit")
|
||||
PERFCOUNTER_CPU(shadow2_unshadow, "shadow2 unshadows a page")
|
||||
PERFCOUNTER_CPU(shadow2_up_pointer, "shadow2 unshadow by up-pointer")
|
||||
PERFCOUNTER_CPU(shadow2_unshadow_bf, "shadow2 unshadow brute-force")
|
||||
PERFCOUNTER_CPU(shadow2_get_page_fail, "shadow2_get_page_from_l1e failed")
|
||||
PERFCOUNTER_CPU(shadow2_guest_walk, "shadow2 walks guest tables")
|
||||
PERFCOUNTER_CPU(shadow2_walk_cache_hit, "shadow2 walk-cache hits")
|
||||
PERFCOUNTER_CPU(shadow2_walk_cache_miss, "shadow2 walk-cache misses")
|
||||
PERFSTATUS(shadow_alloc_count, "number of shadow pages in use")
|
||||
PERFCOUNTER_CPU(shadow_free, "calls to shadow_free")
|
||||
PERFCOUNTER_CPU(shadow_prealloc_1, "shadow recycles old shadows")
|
||||
PERFCOUNTER_CPU(shadow_prealloc_2, "shadow recycles in-use shadows")
|
||||
PERFCOUNTER_CPU(shadow_linear_map_failed, "shadow hit read-only linear map")
|
||||
PERFCOUNTER_CPU(shadow_a_update, "shadow A bit update")
|
||||
PERFCOUNTER_CPU(shadow_ad_update, "shadow A&D bit update")
|
||||
PERFCOUNTER_CPU(shadow_fault, "calls to shadow_fault")
|
||||
PERFCOUNTER_CPU(shadow_fault_bail_bad_gfn, "shadow_fault guest bad gfn")
|
||||
PERFCOUNTER_CPU(shadow_fault_bail_not_present,
|
||||
"shadow_fault guest not-present")
|
||||
PERFCOUNTER_CPU(shadow_fault_bail_nx, "shadow_fault guest NX fault")
|
||||
PERFCOUNTER_CPU(shadow_fault_bail_ro_mapping, "shadow_fault guest R/W fault")
|
||||
PERFCOUNTER_CPU(shadow_fault_bail_user_supervisor,
|
||||
"shadow_fault guest U/S fault")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_read, "shadow_fault emulates a read")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_write, "shadow_fault emulates a write")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_failed, "shadow_fault emulator fails")
|
||||
PERFCOUNTER_CPU(shadow_fault_mmio, "shadow_fault handled as mmio")
|
||||
PERFCOUNTER_CPU(shadow_fault_fixed, "shadow_fault fixed fault")
|
||||
PERFCOUNTER_CPU(shadow_ptwr_emulate, "shadow causes ptwr to emulate")
|
||||
PERFCOUNTER_CPU(shadow_validate_gl1e_calls, "calls to shadow_validate_gl1e")
|
||||
PERFCOUNTER_CPU(shadow_validate_gl2e_calls, "calls to shadow_validate_gl2e")
|
||||
PERFCOUNTER_CPU(shadow_validate_gl3e_calls, "calls to shadow_validate_gl3e")
|
||||
PERFCOUNTER_CPU(shadow_validate_gl4e_calls, "calls to shadow_validate_gl4e")
|
||||
PERFCOUNTER_CPU(shadow_hash_lookups, "calls to shadow_hash_lookup")
|
||||
PERFCOUNTER_CPU(shadow_hash_lookup_head, "shadow hash hit in bucket head")
|
||||
PERFCOUNTER_CPU(shadow_hash_lookup_miss, "shadow hash misses")
|
||||
PERFCOUNTER_CPU(shadow_get_shadow_status, "calls to get_shadow_status")
|
||||
PERFCOUNTER_CPU(shadow_hash_inserts, "calls to shadow_hash_insert")
|
||||
PERFCOUNTER_CPU(shadow_hash_deletes, "calls to shadow_hash_delete")
|
||||
PERFCOUNTER_CPU(shadow_writeable, "shadow removes write access")
|
||||
PERFCOUNTER_CPU(shadow_writeable_h_1, "shadow writeable: 32b w2k3")
|
||||
PERFCOUNTER_CPU(shadow_writeable_h_2, "shadow writeable: 32pae w2k3")
|
||||
PERFCOUNTER_CPU(shadow_writeable_h_3, "shadow writeable: 64b w2k3")
|
||||
PERFCOUNTER_CPU(shadow_writeable_h_4, "shadow writeable: 32b linux low")
|
||||
PERFCOUNTER_CPU(shadow_writeable_bf, "shadow writeable brute-force")
|
||||
PERFCOUNTER_CPU(shadow_mappings, "shadow removes all mappings")
|
||||
PERFCOUNTER_CPU(shadow_mappings_bf, "shadow rm-mappings brute-force")
|
||||
PERFCOUNTER_CPU(shadow_early_unshadow, "shadow unshadows for fork/exit")
|
||||
PERFCOUNTER_CPU(shadow_early_unshadow_top, "shadow unhooks for fork/exit")
|
||||
PERFCOUNTER_CPU(shadow_unshadow, "shadow unshadows a page")
|
||||
PERFCOUNTER_CPU(shadow_up_pointer, "shadow unshadow by up-pointer")
|
||||
PERFCOUNTER_CPU(shadow_unshadow_bf, "shadow unshadow brute-force")
|
||||
PERFCOUNTER_CPU(shadow_get_page_fail, "shadow_get_page_from_l1e failed")
|
||||
PERFCOUNTER_CPU(shadow_guest_walk, "shadow walks guest tables")
|
||||
PERFCOUNTER_CPU(shadow_walk_cache_hit, "shadow walk-cache hits")
|
||||
PERFCOUNTER_CPU(shadow_walk_cache_miss, "shadow walk-cache misses")
|
||||
|
||||
|
||||
/*#endif*/ /* __XEN_PERFC_DEFN_H__ */
|
||||
+598
-14
@@ -1,7 +1,9 @@
|
||||
/******************************************************************************
|
||||
* include/asm-x86/shadow.h
|
||||
*
|
||||
* Copyright (c) 2006 by XenSource Inc.
|
||||
* 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
|
||||
@@ -21,26 +23,608 @@
|
||||
#ifndef _XEN_SHADOW_H
|
||||
#define _XEN_SHADOW_H
|
||||
|
||||
/* This file is just a wrapper around the new Shadow2 header,
|
||||
* providing names that must be defined in any shadow implementation. */
|
||||
|
||||
#include <asm/shadow2.h>
|
||||
#include <public/domctl.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/perfc.h>
|
||||
#include <asm/flushtlb.h>
|
||||
|
||||
/* How to make sure a page is not referred to in a shadow PT */
|
||||
/* This will need to be a for_each_vcpu if we go to per-vcpu shadows */
|
||||
#define shadow_drop_references(_d, _p) \
|
||||
shadow2_remove_all_mappings((_d)->vcpu[0], _mfn(page_to_mfn(_p)))
|
||||
shadow_remove_all_mappings((_d)->vcpu[0], _mfn(page_to_mfn(_p)))
|
||||
#define shadow_sync_and_drop_references(_d, _p) \
|
||||
shadow2_remove_all_mappings((_d)->vcpu[0], _mfn(page_to_mfn(_p)))
|
||||
shadow_remove_all_mappings((_d)->vcpu[0], _mfn(page_to_mfn(_p)))
|
||||
|
||||
/* Whether we are translating the domain's frame numbers for it */
|
||||
#define shadow_mode_translate(d) shadow2_mode_translate(d)
|
||||
|
||||
/* ...and if so, how to add and remove entries in the mapping */
|
||||
/* How to add and remove entries in the p2m mapping. */
|
||||
#define guest_physmap_add_page(_d, _p, _m) \
|
||||
shadow2_guest_physmap_add_page((_d), (_p), (_m))
|
||||
shadow_guest_physmap_add_page((_d), (_p), (_m))
|
||||
#define guest_physmap_remove_page(_d, _p, _m ) \
|
||||
shadow2_guest_physmap_remove_page((_d), (_p), (_m))
|
||||
shadow_guest_physmap_remove_page((_d), (_p), (_m))
|
||||
|
||||
/* Shadow PT operation mode : shadow-mode variable in arch_domain. */
|
||||
|
||||
#define SHM2_shift 10
|
||||
/* We're in one of the shadow modes */
|
||||
#define SHM2_enable (1U << SHM2_shift)
|
||||
/* Refcounts based on shadow tables instead of guest tables */
|
||||
#define SHM2_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << SHM2_shift)
|
||||
/* Enable log dirty mode */
|
||||
#define SHM2_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << SHM2_shift)
|
||||
/* Xen does p2m translation, not guest */
|
||||
#define SHM2_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << SHM2_shift)
|
||||
/* Xen does not steal address space from the domain for its own booking;
|
||||
* requires VT or similar mechanisms */
|
||||
#define SHM2_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << SHM2_shift)
|
||||
|
||||
#define shadow_mode_enabled(_d) ((_d)->arch.shadow.mode)
|
||||
#define shadow_mode_refcounts(_d) ((_d)->arch.shadow.mode & SHM2_refcounts)
|
||||
#define shadow_mode_log_dirty(_d) ((_d)->arch.shadow.mode & SHM2_log_dirty)
|
||||
#define shadow_mode_translate(_d) ((_d)->arch.shadow.mode & SHM2_translate)
|
||||
#define shadow_mode_external(_d) ((_d)->arch.shadow.mode & SHM2_external)
|
||||
|
||||
/* Xen traps & emulates all reads of all page table pages:
|
||||
*not yet supported
|
||||
*/
|
||||
#define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; })
|
||||
|
||||
// flags used in the return value of the shadow_set_lXe() functions...
|
||||
#define SHADOW_SET_CHANGED 0x1
|
||||
#define SHADOW_SET_FLUSH 0x2
|
||||
#define SHADOW_SET_ERROR 0x4
|
||||
#define SHADOW_SET_L3PAE_RECOPY 0x8
|
||||
|
||||
// How do we tell that we have a 32-bit PV guest in a 64-bit Xen?
|
||||
#ifdef __x86_64__
|
||||
#define pv_32bit_guest(_v) 0 // not yet supported
|
||||
#else
|
||||
#define pv_32bit_guest(_v) !hvm_guest(v)
|
||||
#endif
|
||||
|
||||
/* The shadow lock.
|
||||
*
|
||||
* This lock is per-domain. It is intended to allow us to make atomic
|
||||
* updates to the software TLB that the shadow tables provide.
|
||||
*
|
||||
* Specifically, it protects:
|
||||
* - all changes to shadow page table pages
|
||||
* - the shadow hash table
|
||||
* - the shadow page allocator
|
||||
* - all changes to guest page table pages; if/when the notion of
|
||||
* out-of-sync pages is added to this code, then the shadow lock is
|
||||
* protecting all guest page table pages which are not listed as
|
||||
* currently as both guest-writable and out-of-sync...
|
||||
* XXX -- need to think about this relative to writable page tables.
|
||||
* - all changes to the page_info->tlbflush_timestamp
|
||||
* - the page_info->count fields on shadow pages
|
||||
* - the shadow dirty bit array and count
|
||||
* - XXX
|
||||
*/
|
||||
#ifndef CONFIG_SMP
|
||||
#error shadow.h currently requires CONFIG_SMP
|
||||
#endif
|
||||
|
||||
#define shadow_lock_init(_d) \
|
||||
do { \
|
||||
spin_lock_init(&(_d)->arch.shadow.lock); \
|
||||
(_d)->arch.shadow.locker = -1; \
|
||||
(_d)->arch.shadow.locker_function = "nobody"; \
|
||||
} while (0)
|
||||
|
||||
#define shadow_lock_is_acquired(_d) \
|
||||
(current->processor == (_d)->arch.shadow.locker)
|
||||
|
||||
#define shadow_lock(_d) \
|
||||
do { \
|
||||
if ( unlikely((_d)->arch.shadow.locker == current->processor) ) \
|
||||
{ \
|
||||
printk("Error: shadow lock held by %s\n", \
|
||||
(_d)->arch.shadow.locker_function); \
|
||||
BUG(); \
|
||||
} \
|
||||
spin_lock(&(_d)->arch.shadow.lock); \
|
||||
ASSERT((_d)->arch.shadow.locker == -1); \
|
||||
(_d)->arch.shadow.locker = current->processor; \
|
||||
(_d)->arch.shadow.locker_function = __func__; \
|
||||
} while (0)
|
||||
|
||||
#define shadow_unlock(_d) \
|
||||
do { \
|
||||
ASSERT((_d)->arch.shadow.locker == current->processor); \
|
||||
(_d)->arch.shadow.locker = -1; \
|
||||
(_d)->arch.shadow.locker_function = "nobody"; \
|
||||
spin_unlock(&(_d)->arch.shadow.lock); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Levels of self-test and paranoia
|
||||
* XXX should go in config files somewhere?
|
||||
*/
|
||||
#define SHADOW_AUDIT_HASH 0x01 /* Check current hash bucket */
|
||||
#define SHADOW_AUDIT_HASH_FULL 0x02 /* Check every hash bucket */
|
||||
#define SHADOW_AUDIT_ENTRIES 0x04 /* Check this walk's shadows */
|
||||
#define SHADOW_AUDIT_ENTRIES_FULL 0x08 /* Check every shadow */
|
||||
#define SHADOW_AUDIT_ENTRIES_MFNS 0x10 /* Check gfn-mfn map in shadows */
|
||||
#define SHADOW_AUDIT_P2M 0x20 /* Check the p2m table */
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define SHADOW_AUDIT 0
|
||||
#define SHADOW_AUDIT_ENABLE 0
|
||||
#else
|
||||
#define SHADOW_AUDIT 0x15 /* Basic audit of all except p2m. */
|
||||
#define SHADOW_AUDIT_ENABLE shadow_audit_enable
|
||||
extern int shadow_audit_enable;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Levels of optimization
|
||||
* XXX should go in config files somewhere?
|
||||
*/
|
||||
#define SHOPT_WRITABLE_HEURISTIC 0x01 /* Guess at RW PTEs via linear maps */
|
||||
#define SHOPT_EARLY_UNSHADOW 0x02 /* Unshadow l1s on fork or exit */
|
||||
|
||||
#define SHADOW_OPTIMIZATIONS 0x03
|
||||
|
||||
|
||||
/* With shadow pagetables, the different kinds of address start
|
||||
* to get get confusing.
|
||||
*
|
||||
* Virtual addresses are what they usually are: the addresses that are used
|
||||
* to accessing memory while the guest is running. The MMU translates from
|
||||
* virtual addresses to machine addresses.
|
||||
*
|
||||
* (Pseudo-)physical addresses are the abstraction of physical memory the
|
||||
* guest uses for allocation and so forth. For the purposes of this code,
|
||||
* we can largely ignore them.
|
||||
*
|
||||
* Guest frame numbers (gfns) are the entries that the guest puts in its
|
||||
* pagetables. For normal paravirtual guests, they are actual frame numbers,
|
||||
* with the translation done by the guest.
|
||||
*
|
||||
* Machine frame numbers (mfns) are the entries that the hypervisor puts
|
||||
* in the shadow page tables.
|
||||
*
|
||||
* Elsewhere in the xen code base, the name "gmfn" is generally used to refer
|
||||
* to a "machine frame number, from the guest's perspective", or in other
|
||||
* words, pseudo-physical frame numbers. However, in the shadow code, the
|
||||
* term "gmfn" means "the mfn of a guest page"; this combines naturally with
|
||||
* other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a
|
||||
* guest L2 page), etc...
|
||||
*/
|
||||
|
||||
/* With this defined, we do some ugly things to force the compiler to
|
||||
* give us type safety between mfns and gfns and other integers.
|
||||
* TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions
|
||||
* that translate beween int and foo_t.
|
||||
*
|
||||
* It does have some performance cost because the types now have
|
||||
* a different storage attribute, so may not want it on all the time. */
|
||||
#ifndef NDEBUG
|
||||
#define TYPE_SAFETY 1
|
||||
#endif
|
||||
|
||||
#ifdef TYPE_SAFETY
|
||||
#define TYPE_SAFE(_type,_name) \
|
||||
typedef struct { _type _name; } _name##_t; \
|
||||
static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \
|
||||
static inline _type _name##_x(_name##_t n) { return n._name; }
|
||||
#else
|
||||
#define TYPE_SAFE(_type,_name) \
|
||||
typedef _type _name##_t; \
|
||||
static inline _name##_t _##_name(_type n) { return n; } \
|
||||
static inline _type _name##_x(_name##_t n) { return n; }
|
||||
#endif
|
||||
|
||||
TYPE_SAFE(unsigned long,mfn)
|
||||
#define SH_PRI_mfn "05lx"
|
||||
|
||||
static inline int
|
||||
valid_mfn(mfn_t m)
|
||||
{
|
||||
return VALID_MFN(mfn_x(m));
|
||||
}
|
||||
|
||||
static inline mfn_t
|
||||
pagetable_get_mfn(pagetable_t pt)
|
||||
{
|
||||
return _mfn(pagetable_get_pfn(pt));
|
||||
}
|
||||
|
||||
static inline pagetable_t
|
||||
pagetable_from_mfn(mfn_t mfn)
|
||||
{
|
||||
return pagetable_from_pfn(mfn_x(mfn));
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow_vcpu_mode_translate(struct vcpu *v)
|
||||
{
|
||||
// Returns true if this VCPU needs to be using the P2M table to translate
|
||||
// between GFNs and MFNs.
|
||||
//
|
||||
// This is true of translated HVM domains on a vcpu which has paging
|
||||
// enabled. (HVM vcpu's with paging disabled are using the p2m table as
|
||||
// its paging table, so no translation occurs in this case.)
|
||||
//
|
||||
return v->arch.shadow.hvm_paging_enabled;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Mode-specific entry points into the shadow code */
|
||||
|
||||
struct x86_emulate_ctxt;
|
||||
struct shadow_paging_mode {
|
||||
int (*page_fault )(struct vcpu *v, unsigned long va,
|
||||
struct cpu_user_regs *regs);
|
||||
int (*invlpg )(struct vcpu *v, unsigned long va);
|
||||
unsigned long (*gva_to_gpa )(struct vcpu *v, unsigned long va);
|
||||
unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va);
|
||||
void (*update_cr3 )(struct vcpu *v);
|
||||
int (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl2e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl2he)(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl3e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl4e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
void (*detach_old_tables )(struct vcpu *v);
|
||||
int (*x86_emulate_write )(struct vcpu *v, unsigned long va,
|
||||
void *src, u32 bytes,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va,
|
||||
unsigned long old,
|
||||
unsigned long new,
|
||||
unsigned int bytes,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va,
|
||||
unsigned long old_lo,
|
||||
unsigned long old_hi,
|
||||
unsigned long new_lo,
|
||||
unsigned long new_hi,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
mfn_t (*make_monitor_table )(struct vcpu *v);
|
||||
void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
|
||||
#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
|
||||
int (*guess_wrmap )(struct vcpu *v,
|
||||
unsigned long vaddr, mfn_t gmfn);
|
||||
#endif
|
||||
/* For outsiders to tell what mode we're in */
|
||||
unsigned int shadow_levels;
|
||||
unsigned int guest_levels;
|
||||
};
|
||||
|
||||
static inline int shadow_guest_paging_levels(struct vcpu *v)
|
||||
{
|
||||
ASSERT(v->arch.shadow.mode != NULL);
|
||||
return v->arch.shadow.mode->guest_levels;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* Entry points into the shadow code */
|
||||
|
||||
/* Turning on shadow test mode */
|
||||
int shadow_test_enable(struct domain *d);
|
||||
|
||||
/* Handler for shadow control ops: enabling and disabling shadow modes,
|
||||
* and log-dirty bitmap ops all happen through here. */
|
||||
int shadow_domctl(struct domain *d,
|
||||
xen_domctl_shadow_op_t *sc,
|
||||
XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
|
||||
|
||||
/* Call when destroying a domain */
|
||||
void shadow_teardown(struct domain *d);
|
||||
|
||||
/* Call once all of the references to the domain have gone away */
|
||||
void shadow_final_teardown(struct domain *d);
|
||||
|
||||
|
||||
/* Mark a page as dirty in the bitmap */
|
||||
void sh_do_mark_dirty(struct domain *d, mfn_t gmfn);
|
||||
static inline void mark_dirty(struct domain *d, unsigned long gmfn)
|
||||
{
|
||||
if ( shadow_mode_log_dirty(d) )
|
||||
{
|
||||
shadow_lock(d);
|
||||
sh_do_mark_dirty(d, _mfn(gmfn));
|
||||
shadow_unlock(d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Internal version, for when the shadow lock is already held */
|
||||
static inline void sh_mark_dirty(struct domain *d, mfn_t gmfn)
|
||||
{
|
||||
ASSERT(shadow_lock_is_acquired(d));
|
||||
if ( shadow_mode_log_dirty(d) )
|
||||
sh_do_mark_dirty(d, gmfn);
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
/* Called from pagefault handler in Xen, and from the HVM trap handlers
|
||||
* for pagefaults. Returns 1 if this fault was an artefact of the
|
||||
* shadow code (and the guest should retry) or 0 if it is not (and the
|
||||
* fault should be handled elsewhere or passed to the guest). */
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
perfc_incrc(shadow_fault);
|
||||
return v->arch.shadow.mode->page_fault(v, va, regs);
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow_invlpg(struct vcpu *v, unsigned long va)
|
||||
/* Called when the guest requests an invlpg. Returns 1 if the invlpg
|
||||
* instruction should be issued on the hardware, or 0 if it's safe not
|
||||
* to do so. */
|
||||
{
|
||||
return v->arch.shadow.mode->invlpg(v, va);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
shadow_gva_to_gpa(struct vcpu *v, unsigned long va)
|
||||
/* Called to translate a guest virtual address to what the *guest*
|
||||
* pagetables would map it to. */
|
||||
{
|
||||
return v->arch.shadow.mode->gva_to_gpa(v, va);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
shadow_gva_to_gfn(struct vcpu *v, unsigned long va)
|
||||
/* Called to translate a guest virtual address to what the *guest*
|
||||
* pagetables would map it to. */
|
||||
{
|
||||
return v->arch.shadow.mode->gva_to_gfn(v, va);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow_update_cr3(struct vcpu *v)
|
||||
/* Updates all the things that are derived from the guest's CR3.
|
||||
* Called when the guest changes CR3. */
|
||||
{
|
||||
shadow_lock(v->domain);
|
||||
v->arch.shadow.mode->update_cr3(v);
|
||||
shadow_unlock(v->domain);
|
||||
}
|
||||
|
||||
|
||||
/* Should be called after CR3 is updated.
|
||||
* Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3.
|
||||
*
|
||||
* Also updates other state derived from CR3 (vcpu->arch.guest_vtable,
|
||||
* shadow_vtable, etc).
|
||||
*
|
||||
* Uses values found in vcpu->arch.(guest_table and guest_table_user), and
|
||||
* for HVM guests, arch.monitor_table and hvm's guest CR3.
|
||||
*
|
||||
* Update ref counts to shadow tables appropriately.
|
||||
* For PAE, relocate L3 entries, if necessary, into low memory.
|
||||
*/
|
||||
static inline void update_cr3(struct vcpu *v)
|
||||
{
|
||||
unsigned long cr3_mfn=0;
|
||||
|
||||
if ( shadow_mode_enabled(v->domain) )
|
||||
{
|
||||
shadow_update_cr3(v);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS == 4
|
||||
if ( !(v->arch.flags & TF_kernel_mode) )
|
||||
cr3_mfn = pagetable_get_pfn(v->arch.guest_table_user);
|
||||
else
|
||||
#endif
|
||||
cr3_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
|
||||
make_cr3(v, cr3_mfn);
|
||||
}
|
||||
|
||||
extern void sh_update_paging_modes(struct vcpu *v);
|
||||
|
||||
/* Should be called to initialise paging structures if the paging mode
|
||||
* has changed, and when bringing up a VCPU for the first time. */
|
||||
static inline void shadow_update_paging_modes(struct vcpu *v)
|
||||
{
|
||||
ASSERT(shadow_mode_enabled(v->domain));
|
||||
shadow_lock(v->domain);
|
||||
sh_update_paging_modes(v);
|
||||
shadow_unlock(v->domain);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow_detach_old_tables(struct vcpu *v)
|
||||
{
|
||||
if ( v->arch.shadow.mode )
|
||||
v->arch.shadow.mode->detach_old_tables(v);
|
||||
}
|
||||
|
||||
static inline mfn_t
|
||||
shadow_make_monitor_table(struct vcpu *v)
|
||||
{
|
||||
return v->arch.shadow.mode->make_monitor_table(v);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow_destroy_monitor_table(struct vcpu *v, mfn_t mmfn)
|
||||
{
|
||||
v->arch.shadow.mode->destroy_monitor_table(v, mmfn);
|
||||
}
|
||||
|
||||
/* Validate a pagetable change from the guest and update the shadows. */
|
||||
extern int shadow_validate_guest_entry(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry);
|
||||
|
||||
/* Update the shadows in response to a pagetable write from a HVM guest */
|
||||
extern void shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn,
|
||||
void *entry, u32 size);
|
||||
|
||||
/* Remove all writeable mappings of a guest frame from the shadows.
|
||||
* Returns non-zero if we need to flush TLBs.
|
||||
* level and fault_addr desribe how we found this to be a pagetable;
|
||||
* level==0 means we have some other reason for revoking write access. */
|
||||
extern int shadow_remove_write_access(struct vcpu *v, mfn_t readonly_mfn,
|
||||
unsigned int level,
|
||||
unsigned long fault_addr);
|
||||
|
||||
/* Remove all mappings of the guest mfn from the shadows.
|
||||
* Returns non-zero if we need to flush TLBs. */
|
||||
extern int shadow_remove_all_mappings(struct vcpu *v, mfn_t target_mfn);
|
||||
|
||||
void
|
||||
shadow_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn);
|
||||
/* This is a HVM page that we thing is no longer a pagetable.
|
||||
* Unshadow it, and recursively unshadow pages that reference it. */
|
||||
|
||||
/* Remove all shadows of the guest mfn. */
|
||||
extern void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all);
|
||||
static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn)
|
||||
{
|
||||
sh_remove_shadows(v, gmfn, 1);
|
||||
}
|
||||
|
||||
/* Add a page to a domain */
|
||||
void
|
||||
shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn,
|
||||
unsigned long mfn);
|
||||
|
||||
/* Remove a page from a domain */
|
||||
void
|
||||
shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn,
|
||||
unsigned long mfn);
|
||||
|
||||
/*
|
||||
* Definitions for the shadow_flags field in page_info.
|
||||
* These flags are stored on *guest* pages...
|
||||
* Bits 1-13 are encodings for the shadow types.
|
||||
*/
|
||||
#define PGC_SH_type_to_index(_type) ((_type) >> PGC_SH_type_shift)
|
||||
#define SHF_page_type_mask \
|
||||
(((1u << (PGC_SH_type_to_index(PGC_SH_max_shadow) + 1u)) - 1u) - \
|
||||
((1u << PGC_SH_type_to_index(PGC_SH_min_shadow)) - 1u))
|
||||
|
||||
#define SHF_L1_32 (1u << PGC_SH_type_to_index(PGC_SH_l1_32_shadow))
|
||||
#define SHF_FL1_32 (1u << PGC_SH_type_to_index(PGC_SH_fl1_32_shadow))
|
||||
#define SHF_L2_32 (1u << PGC_SH_type_to_index(PGC_SH_l2_32_shadow))
|
||||
#define SHF_L1_PAE (1u << PGC_SH_type_to_index(PGC_SH_l1_pae_shadow))
|
||||
#define SHF_FL1_PAE (1u << PGC_SH_type_to_index(PGC_SH_fl1_pae_shadow))
|
||||
#define SHF_L2_PAE (1u << PGC_SH_type_to_index(PGC_SH_l2_pae_shadow))
|
||||
#define SHF_L2H_PAE (1u << PGC_SH_type_to_index(PGC_SH_l2h_pae_shadow))
|
||||
#define SHF_L3_PAE (1u << PGC_SH_type_to_index(PGC_SH_l3_pae_shadow))
|
||||
#define SHF_L1_64 (1u << PGC_SH_type_to_index(PGC_SH_l1_64_shadow))
|
||||
#define SHF_FL1_64 (1u << PGC_SH_type_to_index(PGC_SH_fl1_64_shadow))
|
||||
#define SHF_L2_64 (1u << PGC_SH_type_to_index(PGC_SH_l2_64_shadow))
|
||||
#define SHF_L3_64 (1u << PGC_SH_type_to_index(PGC_SH_l3_64_shadow))
|
||||
#define SHF_L4_64 (1u << PGC_SH_type_to_index(PGC_SH_l4_64_shadow))
|
||||
|
||||
/* Used for hysteresis when automatically unhooking mappings on fork/exit */
|
||||
#define SHF_unhooked_mappings (1u<<31)
|
||||
|
||||
/*
|
||||
* Allocation of shadow pages
|
||||
*/
|
||||
|
||||
/* Return the minumum acceptable number of shadow pages a domain needs */
|
||||
unsigned int shadow_min_acceptable_pages(struct domain *d);
|
||||
|
||||
/* Set the pool of shadow pages to the required number of MB.
|
||||
* Input will be rounded up to at least min_acceptable_shadow_pages().
|
||||
* Returns 0 for success, 1 for failure. */
|
||||
unsigned int shadow_set_allocation(struct domain *d,
|
||||
unsigned int megabytes,
|
||||
int *preempted);
|
||||
|
||||
/* Return the size of the shadow pool, rounded up to the nearest MB */
|
||||
static inline unsigned int shadow_get_allocation(struct domain *d)
|
||||
{
|
||||
unsigned int pg = d->arch.shadow.total_pages;
|
||||
return ((pg >> (20 - PAGE_SHIFT))
|
||||
+ ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Linked list for chaining entries in the shadow hash table.
|
||||
*/
|
||||
struct shadow_hash_entry {
|
||||
struct shadow_hash_entry *next;
|
||||
mfn_t smfn; /* MFN of the shadow */
|
||||
#ifdef _x86_64_ /* Shorten 'n' so we don't waste a whole word on storing 't' */
|
||||
unsigned long n:56; /* MFN of guest PT or GFN of guest superpage */
|
||||
#else
|
||||
unsigned long n; /* MFN of guest PT or GFN of guest superpage */
|
||||
#endif
|
||||
unsigned char t; /* shadow type bits, or 0 for empty */
|
||||
};
|
||||
|
||||
#define SHADOW_HASH_BUCKETS 251
|
||||
/* Other possibly useful primes are 509, 1021, 2039, 4093, 8191, 16381 */
|
||||
|
||||
|
||||
#if SHADOW_OPTIMIZATIONS & SHOPT_CACHE_WALKS
|
||||
/* Optimization: cache the results of guest walks. This helps with MMIO
|
||||
* and emulated writes, which tend to issue very similar walk requests
|
||||
* repeatedly. We keep the results of the last few walks, and blow
|
||||
* away the cache on guest cr3 write, mode change, or page fault. */
|
||||
|
||||
#define SH_WALK_CACHE_ENTRIES 4
|
||||
|
||||
/* Rather than cache a guest walk, which would include mapped pointers
|
||||
* to pages, we cache what a TLB would remember about the walk: the
|
||||
* permissions and the l1 gfn */
|
||||
struct shadow_walk_cache {
|
||||
unsigned long va; /* The virtual address (or 0 == unused) */
|
||||
unsigned long gfn; /* The gfn from the effective l1e */
|
||||
u32 permissions; /* The aggregated permission bits */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Guest physmap (p2m) support */
|
||||
|
||||
/* Walk another domain's P2M table, mapping pages as we go */
|
||||
extern mfn_t
|
||||
sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
|
||||
|
||||
|
||||
/* General conversion function from gfn to mfn */
|
||||
static inline mfn_t
|
||||
sh_gfn_to_mfn(struct domain *d, unsigned long gfn)
|
||||
{
|
||||
if ( !shadow_mode_translate(d) )
|
||||
return _mfn(gfn);
|
||||
else if ( likely(current->domain == d) )
|
||||
return _mfn(get_mfn_from_gpfn(gfn));
|
||||
else
|
||||
return sh_gfn_to_mfn_foreign(d, gfn);
|
||||
}
|
||||
|
||||
// vcpu-specific version of gfn_to_mfn(). This is where we hide the dirty
|
||||
// little secret that, for hvm guests with paging disabled, nearly all of the
|
||||
// shadow code actually think that the guest is running on *untranslated* page
|
||||
// tables (which is actually domain->phys_table).
|
||||
//
|
||||
static inline mfn_t
|
||||
sh_vcpu_gfn_to_mfn(struct vcpu *v, unsigned long gfn)
|
||||
{
|
||||
if ( !shadow_vcpu_mode_translate(v) )
|
||||
return _mfn(gfn);
|
||||
if ( likely(current->domain == v->domain) )
|
||||
return _mfn(get_mfn_from_gpfn(gfn));
|
||||
return sh_gfn_to_mfn_foreign(v->domain, gfn);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
sh_mfn_to_gfn(struct domain *d, mfn_t mfn)
|
||||
{
|
||||
if ( shadow_mode_translate(d) )
|
||||
return get_gpfn_from_mfn(mfn_x(mfn));
|
||||
else
|
||||
return mfn_x(mfn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* _XEN_SHADOW_H */
|
||||
|
||||
@@ -49,7 +633,7 @@
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,626 +0,0 @@
|
||||
/******************************************************************************
|
||||
* include/asm-x86/shadow2.h
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _XEN_SHADOW2_H
|
||||
#define _XEN_SHADOW2_H
|
||||
|
||||
#include <public/domctl.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/perfc.h>
|
||||
#include <asm/flushtlb.h>
|
||||
|
||||
/* Shadow PT operation mode : shadow-mode variable in arch_domain. */
|
||||
|
||||
#define SHM2_shift 10
|
||||
/* We're in one of the shadow modes */
|
||||
#define SHM2_enable (1U << SHM2_shift)
|
||||
/* Refcounts based on shadow tables instead of guest tables */
|
||||
#define SHM2_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << SHM2_shift)
|
||||
/* Enable log dirty mode */
|
||||
#define SHM2_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << SHM2_shift)
|
||||
/* Xen does p2m translation, not guest */
|
||||
#define SHM2_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << SHM2_shift)
|
||||
/* Xen does not steal address space from the domain for its own booking;
|
||||
* requires VT or similar mechanisms */
|
||||
#define SHM2_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << SHM2_shift)
|
||||
|
||||
#define shadow2_mode_enabled(_d) ((_d)->arch.shadow2.mode)
|
||||
#define shadow2_mode_refcounts(_d) ((_d)->arch.shadow2.mode & SHM2_refcounts)
|
||||
#define shadow2_mode_log_dirty(_d) ((_d)->arch.shadow2.mode & SHM2_log_dirty)
|
||||
#define shadow2_mode_translate(_d) ((_d)->arch.shadow2.mode & SHM2_translate)
|
||||
#define shadow2_mode_external(_d) ((_d)->arch.shadow2.mode & SHM2_external)
|
||||
|
||||
/* Xen traps & emulates all reads of all page table pages:
|
||||
*not yet supported
|
||||
*/
|
||||
#define shadow2_mode_trap_reads(_d) ({ (void)(_d); 0; })
|
||||
|
||||
// flags used in the return value of the shadow_set_lXe() functions...
|
||||
#define SHADOW2_SET_CHANGED 0x1
|
||||
#define SHADOW2_SET_FLUSH 0x2
|
||||
#define SHADOW2_SET_ERROR 0x4
|
||||
#define SHADOW2_SET_L3PAE_RECOPY 0x8
|
||||
|
||||
// How do we tell that we have a 32-bit PV guest in a 64-bit Xen?
|
||||
#ifdef __x86_64__
|
||||
#define pv_32bit_guest(_v) 0 // not yet supported
|
||||
#else
|
||||
#define pv_32bit_guest(_v) !hvm_guest(v)
|
||||
#endif
|
||||
|
||||
/* The shadow2 lock.
|
||||
*
|
||||
* This lock is per-domain. It is intended to allow us to make atomic
|
||||
* updates to the software TLB that the shadow tables provide.
|
||||
*
|
||||
* Specifically, it protects:
|
||||
* - all changes to shadow page table pages
|
||||
* - the shadow hash table
|
||||
* - the shadow page allocator
|
||||
* - all changes to guest page table pages; if/when the notion of
|
||||
* out-of-sync pages is added to this code, then the shadow lock is
|
||||
* protecting all guest page table pages which are not listed as
|
||||
* currently as both guest-writable and out-of-sync...
|
||||
* XXX -- need to think about this relative to writable page tables.
|
||||
* - all changes to the page_info->tlbflush_timestamp
|
||||
* - the page_info->count fields on shadow pages
|
||||
* - the shadow dirty bit array and count
|
||||
* - XXX
|
||||
*/
|
||||
#ifndef CONFIG_SMP
|
||||
#error shadow2.h currently requires CONFIG_SMP
|
||||
#endif
|
||||
|
||||
#define shadow2_lock_init(_d) \
|
||||
do { \
|
||||
spin_lock_init(&(_d)->arch.shadow2.lock); \
|
||||
(_d)->arch.shadow2.locker = -1; \
|
||||
(_d)->arch.shadow2.locker_function = "nobody"; \
|
||||
} while (0)
|
||||
|
||||
#define shadow2_lock_is_acquired(_d) \
|
||||
(current->processor == (_d)->arch.shadow2.locker)
|
||||
|
||||
#define shadow2_lock(_d) \
|
||||
do { \
|
||||
if ( unlikely((_d)->arch.shadow2.locker == current->processor) ) \
|
||||
{ \
|
||||
printk("Error: shadow2 lock held by %s\n", \
|
||||
(_d)->arch.shadow2.locker_function); \
|
||||
BUG(); \
|
||||
} \
|
||||
spin_lock(&(_d)->arch.shadow2.lock); \
|
||||
ASSERT((_d)->arch.shadow2.locker == -1); \
|
||||
(_d)->arch.shadow2.locker = current->processor; \
|
||||
(_d)->arch.shadow2.locker_function = __func__; \
|
||||
} while (0)
|
||||
|
||||
#define shadow2_unlock(_d) \
|
||||
do { \
|
||||
ASSERT((_d)->arch.shadow2.locker == current->processor); \
|
||||
(_d)->arch.shadow2.locker = -1; \
|
||||
(_d)->arch.shadow2.locker_function = "nobody"; \
|
||||
spin_unlock(&(_d)->arch.shadow2.lock); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Levels of self-test and paranoia
|
||||
* XXX should go in config files somewhere?
|
||||
*/
|
||||
#define SHADOW2_AUDIT_HASH 0x01 /* Check current hash bucket */
|
||||
#define SHADOW2_AUDIT_HASH_FULL 0x02 /* Check every hash bucket */
|
||||
#define SHADOW2_AUDIT_ENTRIES 0x04 /* Check this walk's shadows */
|
||||
#define SHADOW2_AUDIT_ENTRIES_FULL 0x08 /* Check every shadow */
|
||||
#define SHADOW2_AUDIT_ENTRIES_MFNS 0x10 /* Check gfn-mfn map in shadows */
|
||||
#define SHADOW2_AUDIT_P2M 0x20 /* Check the p2m table */
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define SHADOW2_AUDIT 0
|
||||
#define SHADOW2_AUDIT_ENABLE 0
|
||||
#else
|
||||
#define SHADOW2_AUDIT 0x15 /* Basic audit of all except p2m. */
|
||||
#define SHADOW2_AUDIT_ENABLE shadow2_audit_enable
|
||||
extern int shadow2_audit_enable;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Levels of optimization
|
||||
* XXX should go in config files somewhere?
|
||||
*/
|
||||
#define SH2OPT_WRITABLE_HEURISTIC 0x01 /* Guess at RW PTEs via linear maps */
|
||||
#define SH2OPT_EARLY_UNSHADOW 0x02 /* Unshadow l1s on fork or exit */
|
||||
|
||||
#define SHADOW2_OPTIMIZATIONS 0x03
|
||||
|
||||
|
||||
/* With shadow pagetables, the different kinds of address start
|
||||
* to get get confusing.
|
||||
*
|
||||
* Virtual addresses are what they usually are: the addresses that are used
|
||||
* to accessing memory while the guest is running. The MMU translates from
|
||||
* virtual addresses to machine addresses.
|
||||
*
|
||||
* (Pseudo-)physical addresses are the abstraction of physical memory the
|
||||
* guest uses for allocation and so forth. For the purposes of this code,
|
||||
* we can largely ignore them.
|
||||
*
|
||||
* Guest frame numbers (gfns) are the entries that the guest puts in its
|
||||
* pagetables. For normal paravirtual guests, they are actual frame numbers,
|
||||
* with the translation done by the guest.
|
||||
*
|
||||
* Machine frame numbers (mfns) are the entries that the hypervisor puts
|
||||
* in the shadow page tables.
|
||||
*
|
||||
* Elsewhere in the xen code base, the name "gmfn" is generally used to refer
|
||||
* to a "machine frame number, from the guest's perspective", or in other
|
||||
* words, pseudo-physical frame numbers. However, in the shadow code, the
|
||||
* term "gmfn" means "the mfn of a guest page"; this combines naturally with
|
||||
* other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a
|
||||
* guest L2 page), etc...
|
||||
*/
|
||||
|
||||
/* With this defined, we do some ugly things to force the compiler to
|
||||
* give us type safety between mfns and gfns and other integers.
|
||||
* TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions
|
||||
* that translate beween int and foo_t.
|
||||
*
|
||||
* It does have some performance cost because the types now have
|
||||
* a different storage attribute, so may not want it on all the time. */
|
||||
#ifndef NDEBUG
|
||||
#define TYPE_SAFETY 1
|
||||
#endif
|
||||
|
||||
#ifdef TYPE_SAFETY
|
||||
#define TYPE_SAFE(_type,_name) \
|
||||
typedef struct { _type _name; } _name##_t; \
|
||||
static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \
|
||||
static inline _type _name##_x(_name##_t n) { return n._name; }
|
||||
#else
|
||||
#define TYPE_SAFE(_type,_name) \
|
||||
typedef _type _name##_t; \
|
||||
static inline _name##_t _##_name(_type n) { return n; } \
|
||||
static inline _type _name##_x(_name##_t n) { return n; }
|
||||
#endif
|
||||
|
||||
TYPE_SAFE(unsigned long,mfn)
|
||||
#define SH2_PRI_mfn "05lx"
|
||||
|
||||
static inline int
|
||||
valid_mfn(mfn_t m)
|
||||
{
|
||||
return VALID_MFN(mfn_x(m));
|
||||
}
|
||||
|
||||
static inline mfn_t
|
||||
pagetable_get_mfn(pagetable_t pt)
|
||||
{
|
||||
return _mfn(pagetable_get_pfn(pt));
|
||||
}
|
||||
|
||||
static inline pagetable_t
|
||||
pagetable_from_mfn(mfn_t mfn)
|
||||
{
|
||||
return pagetable_from_pfn(mfn_x(mfn));
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow2_vcpu_mode_translate(struct vcpu *v)
|
||||
{
|
||||
// Returns true if this VCPU needs to be using the P2M table to translate
|
||||
// between GFNs and MFNs.
|
||||
//
|
||||
// This is true of translated HVM domains on a vcpu which has paging
|
||||
// enabled. (HVM vcpu's with paging disabled are using the p2m table as
|
||||
// its paging table, so no translation occurs in this case.)
|
||||
//
|
||||
return v->arch.shadow2.hvm_paging_enabled;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Mode-specific entry points into the shadow code */
|
||||
|
||||
struct x86_emulate_ctxt;
|
||||
struct shadow2_paging_mode {
|
||||
int (*page_fault )(struct vcpu *v, unsigned long va,
|
||||
struct cpu_user_regs *regs);
|
||||
int (*invlpg )(struct vcpu *v, unsigned long va);
|
||||
unsigned long (*gva_to_gpa )(struct vcpu *v, unsigned long va);
|
||||
unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va);
|
||||
void (*update_cr3 )(struct vcpu *v);
|
||||
int (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl2e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl2he)(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl3e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
int (*map_and_validate_gl4e )(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry, u32 size);
|
||||
void (*detach_old_tables )(struct vcpu *v);
|
||||
int (*x86_emulate_write )(struct vcpu *v, unsigned long va,
|
||||
void *src, u32 bytes,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va,
|
||||
unsigned long old,
|
||||
unsigned long new,
|
||||
unsigned int bytes,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va,
|
||||
unsigned long old_lo,
|
||||
unsigned long old_hi,
|
||||
unsigned long new_lo,
|
||||
unsigned long new_hi,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
mfn_t (*make_monitor_table )(struct vcpu *v);
|
||||
void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
|
||||
#if SHADOW2_OPTIMIZATIONS & SH2OPT_WRITABLE_HEURISTIC
|
||||
int (*guess_wrmap )(struct vcpu *v,
|
||||
unsigned long vaddr, mfn_t gmfn);
|
||||
#endif
|
||||
/* For outsiders to tell what mode we're in */
|
||||
unsigned int shadow_levels;
|
||||
unsigned int guest_levels;
|
||||
};
|
||||
|
||||
static inline int shadow2_guest_paging_levels(struct vcpu *v)
|
||||
{
|
||||
ASSERT(v->arch.shadow2.mode != NULL);
|
||||
return v->arch.shadow2.mode->guest_levels;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* Entry points into the shadow code */
|
||||
|
||||
/* Turning on shadow2 test mode */
|
||||
int shadow2_test_enable(struct domain *d);
|
||||
|
||||
/* Handler for shadow control ops: enabling and disabling shadow modes,
|
||||
* and log-dirty bitmap ops all happen through here. */
|
||||
int shadow2_domctl(struct domain *d,
|
||||
xen_domctl_shadow_op_t *sc,
|
||||
XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
|
||||
|
||||
/* Call when destroying a domain */
|
||||
void shadow2_teardown(struct domain *d);
|
||||
|
||||
/* Call once all of the references to the domain have gone away */
|
||||
void shadow2_final_teardown(struct domain *d);
|
||||
|
||||
|
||||
/* Mark a page as dirty in the bitmap */
|
||||
void sh2_do_mark_dirty(struct domain *d, mfn_t gmfn);
|
||||
static inline void mark_dirty(struct domain *d, unsigned long gmfn)
|
||||
{
|
||||
if ( shadow2_mode_log_dirty(d) )
|
||||
{
|
||||
shadow2_lock(d);
|
||||
sh2_do_mark_dirty(d, _mfn(gmfn));
|
||||
shadow2_unlock(d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Internal version, for when the shadow lock is already held */
|
||||
static inline void sh2_mark_dirty(struct domain *d, mfn_t gmfn)
|
||||
{
|
||||
ASSERT(shadow2_lock_is_acquired(d));
|
||||
if ( shadow2_mode_log_dirty(d) )
|
||||
sh2_do_mark_dirty(d, gmfn);
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow2_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
/* Called from pagefault handler in Xen, and from the HVM trap handlers
|
||||
* for pagefaults. Returns 1 if this fault was an artefact of the
|
||||
* shadow code (and the guest should retry) or 0 if it is not (and the
|
||||
* fault should be handled elsewhere or passed to the guest). */
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
perfc_incrc(shadow2_fault);
|
||||
return v->arch.shadow2.mode->page_fault(v, va, regs);
|
||||
}
|
||||
|
||||
static inline int
|
||||
shadow2_invlpg(struct vcpu *v, unsigned long va)
|
||||
/* Called when the guest requests an invlpg. Returns 1 if the invlpg
|
||||
* instruction should be issued on the hardware, or 0 if it's safe not
|
||||
* to do so. */
|
||||
{
|
||||
return v->arch.shadow2.mode->invlpg(v, va);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
shadow2_gva_to_gpa(struct vcpu *v, unsigned long va)
|
||||
/* Called to translate a guest virtual address to what the *guest*
|
||||
* pagetables would map it to. */
|
||||
{
|
||||
return v->arch.shadow2.mode->gva_to_gpa(v, va);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
shadow2_gva_to_gfn(struct vcpu *v, unsigned long va)
|
||||
/* Called to translate a guest virtual address to what the *guest*
|
||||
* pagetables would map it to. */
|
||||
{
|
||||
return v->arch.shadow2.mode->gva_to_gfn(v, va);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow2_update_cr3(struct vcpu *v)
|
||||
/* Updates all the things that are derived from the guest's CR3.
|
||||
* Called when the guest changes CR3. */
|
||||
{
|
||||
shadow2_lock(v->domain);
|
||||
v->arch.shadow2.mode->update_cr3(v);
|
||||
shadow2_unlock(v->domain);
|
||||
}
|
||||
|
||||
|
||||
/* Should be called after CR3 is updated.
|
||||
* Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3.
|
||||
*
|
||||
* Also updates other state derived from CR3 (vcpu->arch.guest_vtable,
|
||||
* shadow_vtable, etc).
|
||||
*
|
||||
* Uses values found in vcpu->arch.(guest_table and guest_table_user), and
|
||||
* for HVM guests, arch.monitor_table and hvm's guest CR3.
|
||||
*
|
||||
* Update ref counts to shadow tables appropriately.
|
||||
* For PAE, relocate L3 entries, if necessary, into low memory.
|
||||
*/
|
||||
static inline void update_cr3(struct vcpu *v)
|
||||
{
|
||||
unsigned long cr3_mfn=0;
|
||||
|
||||
if ( shadow2_mode_enabled(v->domain) )
|
||||
{
|
||||
shadow2_update_cr3(v);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS == 4
|
||||
if ( !(v->arch.flags & TF_kernel_mode) )
|
||||
cr3_mfn = pagetable_get_pfn(v->arch.guest_table_user);
|
||||
else
|
||||
#endif
|
||||
cr3_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
|
||||
make_cr3(v, cr3_mfn);
|
||||
}
|
||||
|
||||
extern void sh2_update_paging_modes(struct vcpu *v);
|
||||
|
||||
/* Should be called to initialise paging structures if the paging mode
|
||||
* has changed, and when bringing up a VCPU for the first time. */
|
||||
static inline void shadow2_update_paging_modes(struct vcpu *v)
|
||||
{
|
||||
ASSERT(shadow2_mode_enabled(v->domain));
|
||||
shadow2_lock(v->domain);
|
||||
sh2_update_paging_modes(v);
|
||||
shadow2_unlock(v->domain);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow2_detach_old_tables(struct vcpu *v)
|
||||
{
|
||||
if ( v->arch.shadow2.mode )
|
||||
v->arch.shadow2.mode->detach_old_tables(v);
|
||||
}
|
||||
|
||||
static inline mfn_t
|
||||
shadow2_make_monitor_table(struct vcpu *v)
|
||||
{
|
||||
return v->arch.shadow2.mode->make_monitor_table(v);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shadow2_destroy_monitor_table(struct vcpu *v, mfn_t mmfn)
|
||||
{
|
||||
v->arch.shadow2.mode->destroy_monitor_table(v, mmfn);
|
||||
}
|
||||
|
||||
/* Validate a pagetable change from the guest and update the shadows. */
|
||||
extern int shadow2_validate_guest_entry(struct vcpu *v, mfn_t gmfn,
|
||||
void *new_guest_entry);
|
||||
|
||||
/* Update the shadows in response to a pagetable write from a HVM guest */
|
||||
extern void shadow2_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn,
|
||||
void *entry, u32 size);
|
||||
|
||||
/* Remove all writeable mappings of a guest frame from the shadows.
|
||||
* Returns non-zero if we need to flush TLBs.
|
||||
* level and fault_addr desribe how we found this to be a pagetable;
|
||||
* level==0 means we have some other reason for revoking write access. */
|
||||
extern int shadow2_remove_write_access(struct vcpu *v, mfn_t readonly_mfn,
|
||||
unsigned int level,
|
||||
unsigned long fault_addr);
|
||||
|
||||
/* Remove all mappings of the guest mfn from the shadows.
|
||||
* Returns non-zero if we need to flush TLBs. */
|
||||
extern int shadow2_remove_all_mappings(struct vcpu *v, mfn_t target_mfn);
|
||||
|
||||
void
|
||||
shadow2_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn);
|
||||
/* This is a HVM page that we thing is no longer a pagetable.
|
||||
* Unshadow it, and recursively unshadow pages that reference it. */
|
||||
|
||||
/* Remove all shadows of the guest mfn. */
|
||||
extern void sh2_remove_shadows(struct vcpu *v, mfn_t gmfn, int all);
|
||||
static inline void shadow2_remove_all_shadows(struct vcpu *v, mfn_t gmfn)
|
||||
{
|
||||
sh2_remove_shadows(v, gmfn, 1);
|
||||
}
|
||||
|
||||
/* Add a page to a domain */
|
||||
void
|
||||
shadow2_guest_physmap_add_page(struct domain *d, unsigned long gfn,
|
||||
unsigned long mfn);
|
||||
|
||||
/* Remove a page from a domain */
|
||||
void
|
||||
shadow2_guest_physmap_remove_page(struct domain *d, unsigned long gfn,
|
||||
unsigned long mfn);
|
||||
|
||||
/*
|
||||
* Definitions for the shadow2_flags field in page_info.
|
||||
* These flags are stored on *guest* pages...
|
||||
* Bits 1-13 are encodings for the shadow types.
|
||||
*/
|
||||
#define PGC_SH2_type_to_index(_type) ((_type) >> PGC_SH2_type_shift)
|
||||
#define SH2F_page_type_mask \
|
||||
(((1u << (PGC_SH2_type_to_index(PGC_SH2_max_shadow) + 1u)) - 1u) - \
|
||||
((1u << PGC_SH2_type_to_index(PGC_SH2_min_shadow)) - 1u))
|
||||
|
||||
#define SH2F_L1_32 (1u << PGC_SH2_type_to_index(PGC_SH2_l1_32_shadow))
|
||||
#define SH2F_FL1_32 (1u << PGC_SH2_type_to_index(PGC_SH2_fl1_32_shadow))
|
||||
#define SH2F_L2_32 (1u << PGC_SH2_type_to_index(PGC_SH2_l2_32_shadow))
|
||||
#define SH2F_L1_PAE (1u << PGC_SH2_type_to_index(PGC_SH2_l1_pae_shadow))
|
||||
#define SH2F_FL1_PAE (1u << PGC_SH2_type_to_index(PGC_SH2_fl1_pae_shadow))
|
||||
#define SH2F_L2_PAE (1u << PGC_SH2_type_to_index(PGC_SH2_l2_pae_shadow))
|
||||
#define SH2F_L2H_PAE (1u << PGC_SH2_type_to_index(PGC_SH2_l2h_pae_shadow))
|
||||
#define SH2F_L3_PAE (1u << PGC_SH2_type_to_index(PGC_SH2_l3_pae_shadow))
|
||||
#define SH2F_L1_64 (1u << PGC_SH2_type_to_index(PGC_SH2_l1_64_shadow))
|
||||
#define SH2F_FL1_64 (1u << PGC_SH2_type_to_index(PGC_SH2_fl1_64_shadow))
|
||||
#define SH2F_L2_64 (1u << PGC_SH2_type_to_index(PGC_SH2_l2_64_shadow))
|
||||
#define SH2F_L3_64 (1u << PGC_SH2_type_to_index(PGC_SH2_l3_64_shadow))
|
||||
#define SH2F_L4_64 (1u << PGC_SH2_type_to_index(PGC_SH2_l4_64_shadow))
|
||||
|
||||
/* Used for hysteresis when automatically unhooking mappings on fork/exit */
|
||||
#define SH2F_unhooked_mappings (1u<<31)
|
||||
|
||||
/*
|
||||
* Allocation of shadow pages
|
||||
*/
|
||||
|
||||
/* Return the minumum acceptable number of shadow pages a domain needs */
|
||||
unsigned int shadow2_min_acceptable_pages(struct domain *d);
|
||||
|
||||
/* Set the pool of shadow pages to the required number of MB.
|
||||
* Input will be rounded up to at least min_acceptable_shadow_pages().
|
||||
* Returns 0 for success, 1 for failure. */
|
||||
unsigned int shadow2_set_allocation(struct domain *d,
|
||||
unsigned int megabytes,
|
||||
int *preempted);
|
||||
|
||||
/* Return the size of the shadow2 pool, rounded up to the nearest MB */
|
||||
static inline unsigned int shadow2_get_allocation(struct domain *d)
|
||||
{
|
||||
unsigned int pg = d->arch.shadow2.total_pages;
|
||||
return ((pg >> (20 - PAGE_SHIFT))
|
||||
+ ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Linked list for chaining entries in the shadow hash table.
|
||||
*/
|
||||
struct shadow2_hash_entry {
|
||||
struct shadow2_hash_entry *next;
|
||||
mfn_t smfn; /* MFN of the shadow */
|
||||
#ifdef _x86_64_ /* Shorten 'n' so we don't waste a whole word on storing 't' */
|
||||
unsigned long n:56; /* MFN of guest PT or GFN of guest superpage */
|
||||
#else
|
||||
unsigned long n; /* MFN of guest PT or GFN of guest superpage */
|
||||
#endif
|
||||
unsigned char t; /* shadow type bits, or 0 for empty */
|
||||
};
|
||||
|
||||
#define SHADOW2_HASH_BUCKETS 251
|
||||
/* Other possibly useful primes are 509, 1021, 2039, 4093, 8191, 16381 */
|
||||
|
||||
|
||||
#if SHADOW2_OPTIMIZATIONS & SH2OPT_CACHE_WALKS
|
||||
/* Optimization: cache the results of guest walks. This helps with MMIO
|
||||
* and emulated writes, which tend to issue very similar walk requests
|
||||
* repeatedly. We keep the results of the last few walks, and blow
|
||||
* away the cache on guest cr3 write, mode change, or page fault. */
|
||||
|
||||
#define SH2_WALK_CACHE_ENTRIES 4
|
||||
|
||||
/* Rather than cache a guest walk, which would include mapped pointers
|
||||
* to pages, we cache what a TLB would remember about the walk: the
|
||||
* permissions and the l1 gfn */
|
||||
struct shadow2_walk_cache {
|
||||
unsigned long va; /* The virtual address (or 0 == unused) */
|
||||
unsigned long gfn; /* The gfn from the effective l1e */
|
||||
u32 permissions; /* The aggregated permission bits */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Guest physmap (p2m) support */
|
||||
|
||||
/* Walk another domain's P2M table, mapping pages as we go */
|
||||
extern mfn_t
|
||||
sh2_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
|
||||
|
||||
|
||||
/* General conversion function from gfn to mfn */
|
||||
static inline mfn_t
|
||||
sh2_gfn_to_mfn(struct domain *d, unsigned long gfn)
|
||||
{
|
||||
if ( !shadow2_mode_translate(d) )
|
||||
return _mfn(gfn);
|
||||
else if ( likely(current->domain == d) )
|
||||
return _mfn(get_mfn_from_gpfn(gfn));
|
||||
else
|
||||
return sh2_gfn_to_mfn_foreign(d, gfn);
|
||||
}
|
||||
|
||||
// vcpu-specific version of gfn_to_mfn(). This is where we hide the dirty
|
||||
// little secret that, for hvm guests with paging disabled, nearly all of the
|
||||
// shadow code actually think that the guest is running on *untranslated* page
|
||||
// tables (which is actually domain->phys_table).
|
||||
//
|
||||
static inline mfn_t
|
||||
sh2_vcpu_gfn_to_mfn(struct vcpu *v, unsigned long gfn)
|
||||
{
|
||||
if ( !shadow2_vcpu_mode_translate(v) )
|
||||
return _mfn(gfn);
|
||||
if ( likely(current->domain == v->domain) )
|
||||
return _mfn(get_mfn_from_gpfn(gfn));
|
||||
return sh2_gfn_to_mfn_foreign(v->domain, gfn);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
sh2_mfn_to_gfn(struct domain *d, mfn_t mfn)
|
||||
{
|
||||
if ( shadow2_mode_translate(d) )
|
||||
return get_gpfn_from_mfn(mfn_x(mfn));
|
||||
else
|
||||
return mfn_x(mfn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* _XEN_SHADOW2_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||