This commit is contained in:
Stefano Stabellini committed 2010-08-11 15:56:01 +01:00
commit e6bde27c82
47 files changed
+1377 -681

No files matched your search

+2 -4
View File
@@ -1,8 +1,6 @@
XEN_ROOT = ../../..
include ./Rules.mk
sbindir=/usr/sbin
.PHONY: all
all:
$(MAKE) -C gx
@@ -16,8 +14,8 @@ clean:
.PHONY: install
install: all
[ -d $(DESTDIR)$(sbindir) ] || $(INSTALL_DIR) $(DESTDIR)$(sbindir)
$(INSTALL_PROG) gdbsx $(DESTDIR)$(sbindir)/gdbsx
[ -d $(DESTDIR)$(SBINDIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
$(INSTALL_PROG) gdbsx $(DESTDIR)$(SBINDIR)/gdbsx
gdbsx: gx/gx_all.a xg/xg_all.a
$(CC) -o $@ $^
+1 -1
View File
@@ -61,7 +61,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr)
return INVALID_MFN;
}
mfn = mfn_x(gfn_to_mfn(dp, gfn, &gfntype));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(dp), gfn, &gfntype));
if ( p2m_is_readonly(gfntype) && toaddr )
{
DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
+1 -1
View File
@@ -151,7 +151,7 @@ void dump_pageframe_info(struct domain *d)
if ( is_hvm_domain(d) )
{
p2m_pod_dump_data(d);
p2m_pod_dump_data(p2m_get_hostp2m(d));
}
spin_lock(&d->page_alloc_lock);
+2 -2
View File
@@ -982,7 +982,7 @@ long arch_do_domctl(
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
for ( i = 0; i < nr_mfns; i++ )
set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i));
set_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i, _mfn(mfn+i));
}
else
{
@@ -991,7 +991,7 @@ long arch_do_domctl(
gfn, mfn, nr_mfns);
for ( i = 0; i < nr_mfns; i++ )
clear_mmio_p2m_entry(d, gfn+i);
clear_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i);
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
}
+6 -4
View File
@@ -55,6 +55,7 @@ int hvmemul_do_io(
paddr_t value = ram_gpa;
int value_is_ptr = (p_data == NULL);
struct vcpu *curr = current;
struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
ioreq_t *p = get_ioreq(curr);
unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
p2m_type_t p2mt;
@@ -62,10 +63,10 @@ int hvmemul_do_io(
int rc;
/* Check for paged out page */
ram_mfn = gfn_to_mfn_unshare(current->domain, ram_gfn, &p2mt, 0);
ram_mfn = gfn_to_mfn_unshare(p2m, ram_gfn, &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(curr->domain, ram_gfn);
p2m_mem_paging_populate(p2m, ram_gfn);
return X86EMUL_RETRY;
}
if ( p2m_is_shared(p2mt) )
@@ -638,6 +639,7 @@ static int hvmemul_rep_movs(
unsigned long saddr, daddr, bytes;
paddr_t sgpa, dgpa;
uint32_t pfec = PFEC_page_present;
struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
p2m_type_t p2mt;
int rc, df = !!(ctxt->regs->eflags & X86_EFLAGS_DF);
char *buf;
@@ -668,12 +670,12 @@ static int hvmemul_rep_movs(
if ( rc != X86EMUL_OKAY )
return rc;
(void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
(void)gfn_to_mfn(p2m, sgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
return hvmemul_do_mmio(
sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
(void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
(void)gfn_to_mfn(p2m, dgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
return hvmemul_do_mmio(
dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
+55 -41
View File
@@ -335,16 +335,17 @@ static int hvm_set_ioreq_page(
struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn)
{
struct page_info *page;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_type_t p2mt;
unsigned long mfn;
void *va;
mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn, &p2mt, 0));
mfn = mfn_x(gfn_to_mfn_unshare(p2m, gmfn, &p2mt, 0));
if ( !p2m_is_ram(p2mt) )
return -EINVAL;
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(d, gmfn);
p2m_mem_paging_populate(p2m, gmfn);
return -ENOENT;
}
if ( p2m_is_shared(p2mt) )
@@ -968,8 +969,10 @@ bool_t hvm_hap_nested_page_fault(unsigned long gfn)
{
p2m_type_t p2mt;
mfn_t mfn;
struct vcpu *v = current;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
/*
* If this GFN is emulated MMIO or marked as read-only, pass the fault
@@ -985,12 +988,12 @@ bool_t hvm_hap_nested_page_fault(unsigned long gfn)
#ifdef __x86_64__
/* Check if the page has been paged out */
if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
p2m_mem_paging_populate(current->domain, gfn);
p2m_mem_paging_populate(p2m, gfn);
/* Mem sharing: unshare the page and try again */
if ( p2mt == p2m_ram_shared )
{
mem_sharing_unshare_page(current->domain, gfn, 0);
mem_sharing_unshare_page(p2m, gfn, 0);
return 1;
}
#endif
@@ -1003,8 +1006,8 @@ bool_t hvm_hap_nested_page_fault(unsigned long gfn)
* a large page, we do not change other pages type within that large
* page.
*/
paging_mark_dirty(current->domain, mfn_x(mfn));
p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
paging_mark_dirty(v->domain, mfn_x(mfn));
p2m_change_type(p2m, gfn, p2m_ram_logdirty, p2m_ram_rw);
return 1;
}
@@ -1088,6 +1091,7 @@ int hvm_set_cr0(unsigned long value)
{
struct vcpu *v = current;
p2m_type_t p2mt;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
unsigned long gfn, mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
@@ -1126,7 +1130,7 @@ int hvm_set_cr0(unsigned long value)
{
/* The guest CR3 must be pointing to the guest physical. */
gfn = v->arch.hvm_vcpu.guest_cr[3]>>PAGE_SHIFT;
mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m, gfn, &p2mt));
if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
!get_page(mfn_to_page(mfn), v->domain))
{
@@ -1213,7 +1217,8 @@ int hvm_set_cr3(unsigned long value)
{
/* Shadow-mode CR3 change. Check PDBR and update refcounts. */
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
mfn = mfn_x(gfn_to_mfn_current(value >> PAGE_SHIFT, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
value >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
!get_page(mfn_to_page(mfn), v->domain) )
goto bad_cr3;
@@ -1356,6 +1361,8 @@ static void *hvm_map_entry(unsigned long va)
unsigned long gfn, mfn;
p2m_type_t p2mt;
uint32_t pfec;
struct vcpu *v = current;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
if ( ((va & ~PAGE_MASK) + 8) > PAGE_SIZE )
{
@@ -1372,10 +1379,10 @@ static void *hvm_map_entry(unsigned long va)
gfn = paging_gva_to_gfn(current, va, &pfec);
if ( pfec == PFEC_page_paged || pfec == PFEC_page_shared )
return NULL;
mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(current->domain, gfn);
p2m_mem_paging_populate(p2m, gfn);
return NULL;
}
if ( p2m_is_shared(p2mt) )
@@ -1742,6 +1749,7 @@ static enum hvm_copy_result __hvm_copy(
void *buf, paddr_t addr, int size, unsigned int flags, uint32_t pfec)
{
struct vcpu *curr = current;
struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
unsigned long gfn, mfn;
p2m_type_t p2mt;
char *p;
@@ -1770,11 +1778,11 @@ static enum hvm_copy_result __hvm_copy(
gfn = addr >> PAGE_SHIFT;
}
mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(curr->domain, gfn);
p2m_mem_paging_populate(p2m, gfn);
return HVMCOPY_gfn_paged_out;
}
if ( p2m_is_shared(p2mt) )
@@ -2021,7 +2029,7 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
uint64_t *var_range_base, *fixed_range_base;
int index, mtrr;
uint32_t cpuid[4];
int ret;
int ret = X86EMUL_OKAY;
var_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.var_ranges;
fixed_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.fixed_ranges;
@@ -2094,24 +2102,25 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
break;
default:
ret = vmce_rdmsr(msr, msr_content);
if ( ret < 0 )
if ( (ret = vmce_rdmsr(msr, msr_content)) < 0 )
goto gp_fault;
else if ( ret )
break;
/* ret == 0, This is not an MCE MSR, see other MSRs */
else if (!ret) {
return hvm_funcs.msr_read_intercept(msr, msr_content);
}
/* If ret == 0 then this is not an MCE MSR, see other MSRs. */
ret = ((ret == 0)
? hvm_funcs.msr_read_intercept(msr, msr_content)
: X86EMUL_OKAY);
break;
}
HVMTRACE_3D(MSR_READ, (uint32_t)*msr_content, (uint32_t)(*msr_content >> 32), msr);
out:
HVMTRACE_3D(MSR_READ, msr,
(uint32_t)*msr_content, (uint32_t)(*msr_content >> 32));
return ret;
return X86EMUL_OKAY;
gp_fault:
gp_fault:
hvm_inject_exception(TRAP_gp_fault, 0, 0);
return X86EMUL_EXCEPTION;
ret = X86EMUL_EXCEPTION;
*msr_content = -1ull;
goto out;
}
int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
@@ -2119,9 +2128,10 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
struct vcpu *v = current;
int index, mtrr;
uint32_t cpuid[4];
int ret;
int ret = X86EMUL_OKAY;
HVMTRACE_3D(MSR_WRITE, (uint32_t)msr_content, (uint32_t)(msr_content >> 32), msr);
HVMTRACE_3D(MSR_WRITE, msr,
(uint32_t)msr_content, (uint32_t)(msr_content >> 32));
hvm_cpuid(1, &cpuid[0], &cpuid[1], &cpuid[2], &cpuid[3]);
mtrr = !!(cpuid[3] & bitmaskof(X86_FEATURE_MTRR));
@@ -2194,16 +2204,16 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
break;
default:
ret = vmce_wrmsr(msr, msr_content);
if ( ret < 0 )
if ( (ret = vmce_wrmsr(msr, msr_content)) < 0 )
goto gp_fault;
else if ( ret )
break;
else if (!ret)
return hvm_funcs.msr_write_intercept(msr, msr_content);
/* If ret == 0 then this is not an MCE MSR, see other MSRs. */
ret = ((ret == 0)
? hvm_funcs.msr_write_intercept(msr, msr_content)
: X86EMUL_OKAY);
break;
}
return X86EMUL_OKAY;
return ret;
gp_fault:
hvm_inject_exception(TRAP_gp_fault, 0, 0);
@@ -3029,6 +3039,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
{
struct xen_hvm_modified_memory a;
struct domain *d;
struct p2m_domain *p2m;
unsigned long pfn;
if ( copy_from_guest(&a, arg, 1) )
@@ -3056,13 +3067,14 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( !paging_mode_log_dirty(d) )
goto param_fail3;
p2m = p2m_get_hostp2m(d);
for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
{
p2m_type_t t;
mfn_t mfn = gfn_to_mfn(d, pfn, &t);
mfn_t mfn = gfn_to_mfn(p2m, pfn, &t);
if ( p2m_is_paging(t) )
{
p2m_mem_paging_populate(d, pfn);
p2m_mem_paging_populate(p2m, pfn);
rc = -EINVAL;
goto param_fail3;
@@ -3089,6 +3101,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
{
struct xen_hvm_set_mem_type a;
struct domain *d;
struct p2m_domain *p2m;
unsigned long pfn;
/* Interface types to internal p2m types */
@@ -3118,15 +3131,16 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
goto param_fail4;
p2m = p2m_get_hostp2m(d);
for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
{
p2m_type_t t;
p2m_type_t nt;
mfn_t mfn;
mfn = gfn_to_mfn_unshare(d, pfn, &t, 0);
mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0);
if ( p2m_is_paging(t) )
{
p2m_mem_paging_populate(d, pfn);
p2m_mem_paging_populate(p2m, pfn);
rc = -EINVAL;
goto param_fail4;
@@ -3145,7 +3159,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
}
else
{
nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
nt = p2m_change_type(p2m, pfn, t, memtype[a.hvmmem_type]);
if ( nt != t )
{
gdprintk(XENLOG_WARNING,
+1 -1
View File
@@ -399,7 +399,7 @@ uint32_t get_pat_flags(struct vcpu *v,
{
struct domain *d = v->domain;
p2m_type_t p2mt;
gfn_to_mfn(d, paddr_to_pfn(gpaddr), &p2mt);
gfn_to_mfn(p2m_get_hostp2m(d), paddr_to_pfn(gpaddr), &p2mt);
if (p2m_is_ram(p2mt))
gdprintk(XENLOG_WARNING,
"Conflict occurs for a given guest l1e flags:%x "
+3 -2
View File
@@ -469,6 +469,7 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p)
int i;
int sign = p->df ? -1 : 1;
p2m_type_t p2mt;
struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
if ( p->data_is_ptr )
{
@@ -481,7 +482,7 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p)
if ( hvm_copy_to_guest_phys(data, &tmp, p->size) !=
HVMCOPY_okay )
{
(void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
(void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
/*
* The only case we handle is vga_mem <-> vga_mem.
* Anything else disables caching and leaves it to qemu-dm.
@@ -503,7 +504,7 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p)
if ( hvm_copy_from_guest_phys(&tmp, data, p->size) !=
HVMCOPY_okay )
{
(void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
(void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) )
return 0;
+6 -8
View File
@@ -232,7 +232,7 @@ static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
{
if ( c->cr0 & X86_CR0_PG )
{
mfn = mfn_x(gfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m, c->cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
{
gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
@@ -946,6 +946,9 @@ static void svm_do_nested_pgfault(paddr_t gpa)
unsigned long gfn = gpa >> PAGE_SHIFT;
mfn_t mfn;
p2m_type_t p2mt;
struct p2m_domain *p2m;
p2m = p2m_get_hostp2m(current->domain);
if ( tb_init_done )
{
@@ -958,7 +961,7 @@ static void svm_do_nested_pgfault(paddr_t gpa)
_d.gpa = gpa;
_d.qualification = 0;
_d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
_d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
__trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
}
@@ -967,7 +970,7 @@ static void svm_do_nested_pgfault(paddr_t gpa)
return;
/* Everything else is an error. */
mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
gdprintk(XENLOG_ERR, "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n",
gpa, mfn_x(mfn), p2mt);
domain_crash(current->domain);
@@ -1117,8 +1120,6 @@ static int svm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
goto gpf;
}
HVMTRACE_3D (MSR_READ, msr,
(uint32_t)*msr_content, (uint32_t)(*msr_content>>32));
HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=%"PRIx64,
msr, *msr_content);
return X86EMUL_OKAY;
@@ -1133,9 +1134,6 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
HVMTRACE_3D(MSR_WRITE, msr,
(uint32_t)msr_content, (uint32_t)(msr_content >> 32));
switch ( msr )
{
case MSR_K8_VM_HSAVE_PA:
+29 -9
View File
@@ -159,7 +159,10 @@ struct msixtbl_entry
unsigned long gtable; /* gpa of msix table */
unsigned long table_len;
unsigned long table_flags[MAX_MSIX_TABLE_ENTRIES / BITS_PER_LONG + 1];
#define MAX_MSIX_ACC_ENTRIES 3
struct {
uint32_t msi_ad[3]; /* Shadow of address low, high and data */
} gentries[MAX_MSIX_ACC_ENTRIES];
struct rcu_head rcu;
};
@@ -205,9 +208,10 @@ static int msixtbl_read(
struct vcpu *v, unsigned long address,
unsigned long len, unsigned long *pval)
{
unsigned long offset;
unsigned long offset, val;
struct msixtbl_entry *entry;
void *virt;
int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
rcu_read_lock(&msixtbl_rcu_lock);
@@ -215,18 +219,29 @@ static int msixtbl_read(
if ( len != 4 )
goto out;
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
goto out;
entry = msixtbl_find_entry(v, address);
virt = msixtbl_addr_to_virt(entry, address);
if ( !virt )
goto out;
*pval = readl(virt);
r = X86EMUL_OKAY;
nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
if ( nr_entry >= MAX_MSIX_ACC_ENTRIES &&
offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
goto out;
val = readl(virt);
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
{
index = offset / sizeof(uint32_t);
*pval = entry->gentries[nr_entry].msi_ad[index];
}
else
{
*pval = val;
}
r = X86EMUL_OKAY;
out:
rcu_read_unlock(&msixtbl_rcu_lock);
return r;
@@ -238,7 +253,7 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
unsigned long offset;
struct msixtbl_entry *entry;
void *virt;
int nr_entry;
int nr_entry, index;
int r = X86EMUL_UNHANDLEABLE;
rcu_read_lock(&msixtbl_rcu_lock);
@@ -252,6 +267,11 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
{
if ( nr_entry < MAX_MSIX_ACC_ENTRIES )
{
index = offset / sizeof(uint32_t);
entry->gentries[nr_entry].msi_ad[index] = val;
}
set_bit(nr_entry, &entry->table_flags);
goto out;
}
+11 -12
View File
@@ -486,7 +486,8 @@ static int vmx_restore_cr0_cr3(
{
if ( cr0 & X86_CR0_PG )
{
mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
{
gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%lx\n", cr3);
@@ -1002,7 +1003,8 @@ static void vmx_load_pdptrs(struct vcpu *v)
if ( cr3 & 0x1fUL )
goto crash;
mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) )
goto crash;
@@ -1221,7 +1223,7 @@ void ept_sync_domain(struct domain *d)
return;
ASSERT(local_irq_is_enabled());
ASSERT(p2m_locked_by_me(d->arch.p2m));
ASSERT(p2m_locked_by_me(p2m_get_hostp2m(d)));
/*
* Flush active cpus synchronously. Flush others the next time this domain
@@ -1340,7 +1342,7 @@ static void vmx_set_uc_mode(struct vcpu *v)
{
if ( paging_mode_hap(v->domain) )
ept_change_entry_emt_with_range(
v->domain, 0, v->domain->arch.p2m->max_mapped_pfn);
v->domain, 0, p2m_get_hostp2m(v->domain)->max_mapped_pfn);
hvm_asid_flush_vcpu(v);
}
@@ -1872,8 +1874,6 @@ static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
}
done:
HVMTRACE_3D(MSR_READ, msr,
(uint32_t)*msr_content, (uint32_t)(*msr_content >> 32));
HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=0x%"PRIx64,
msr, *msr_content);
return X86EMUL_OKAY;
@@ -1895,7 +1895,8 @@ static int vmx_alloc_vlapic_mapping(struct domain *d)
return -ENOMEM;
share_xen_page_with_guest(virt_to_page(apic_va), d, XENSHARE_writable);
set_mmio_p2m_entry(
d, paddr_to_pfn(APIC_DEFAULT_PHYS_BASE), _mfn(virt_to_mfn(apic_va)));
p2m_get_hostp2m(d), paddr_to_pfn(APIC_DEFAULT_PHYS_BASE),
_mfn(virt_to_mfn(apic_va)));
d->arch.hvm_domain.vmx.apic_access_mfn = virt_to_mfn(apic_va);
return 0;
@@ -1950,9 +1951,6 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%x, msr_value=0x%"PRIx64,
msr, msr_content);
HVMTRACE_3D(MSR_WRITE, msr,
(uint32_t)msr_content, (uint32_t)(msr_content >> 32));
switch ( msr )
{
case MSR_IA32_SYSENTER_CS:
@@ -2103,6 +2101,7 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa)
unsigned long gla, gfn = gpa >> PAGE_SHIFT;
mfn_t mfn;
p2m_type_t p2mt;
struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
if ( tb_init_done )
{
@@ -2115,7 +2114,7 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa)
_d.gpa = gpa;
_d.qualification = qualification;
_d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
_d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
__trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
}
@@ -2125,7 +2124,7 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa)
return;
/* Everything else is an error. */
mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), "
"gpa %#"PRIpaddr", mfn %#lx, type %i.\n",
qualification,
+32 -25
View File
@@ -398,7 +398,7 @@ int page_is_ram_type(unsigned long mfn, unsigned long mem_type)
unsigned long domain_get_maximum_gpfn(struct domain *d)
{
if ( is_hvm_domain(d) )
return d->arch.p2m->max_mapped_pfn;
return p2m_get_hostp2m(d)->max_mapped_pfn;
/* NB. PV guests specify nr_pfns rather than max_pfn so we adjust here. */
return arch_get_max_pfn(d) - 1;
}
@@ -1741,7 +1741,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
if ( l1e_get_flags(nl1e) & _PAGE_PRESENT )
{
/* Translate foreign guest addresses. */
mfn = mfn_x(gfn_to_mfn(pg_dom, l1e_get_pfn(nl1e), &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pg_dom),
l1e_get_pfn(nl1e), &p2mt));
if ( !p2m_is_ram(p2mt) || unlikely(mfn == INVALID_MFN) )
return 0;
ASSERT((mfn & ~(PADDR_MASK >> PAGE_SHIFT)) == 0);
@@ -3318,8 +3319,8 @@ int do_mmu_update(
struct page_info *page;
int rc = 0, okay = 1, i = 0;
unsigned int cmd, done = 0, pt_dom;
struct domain *d = current->domain, *pt_owner = d, *pg_owner;
struct vcpu *v = current;
struct domain *d = v->domain, *pt_owner = d, *pg_owner;
struct domain_mmap_cache mapcache;
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
@@ -3403,13 +3404,13 @@ int do_mmu_update(
req.ptr -= cmd;
gmfn = req.ptr >> PAGE_SHIFT;
mfn = mfn_x(gfn_to_mfn(pt_owner, gmfn, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pt_owner), gmfn, &p2mt));
if ( !p2m_is_valid(p2mt) )
mfn = INVALID_MFN;
if ( p2m_is_paged(p2mt) )
{
p2m_mem_paging_populate(pg_owner, gmfn);
p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner), gmfn);
rc = -ENOENT;
break;
@@ -3434,12 +3435,13 @@ int do_mmu_update(
{
l1_pgentry_t l1e = l1e_from_intpte(req.val);
p2m_type_t l1e_p2mt;
gfn_to_mfn(pg_owner, l1e_get_pfn(l1e), &l1e_p2mt);
gfn_to_mfn(p2m_get_hostp2m(pg_owner),
l1e_get_pfn(l1e), &l1e_p2mt);
if ( p2m_is_paged(l1e_p2mt) )
{
p2m_mem_paging_populate(pg_owner, l1e_get_pfn(l1e));
p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
l1e_get_pfn(l1e));
rc = -ENOENT;
break;
}
@@ -3457,7 +3459,7 @@ int do_mmu_update(
/* Unshare the page for RW foreign mappings */
if ( l1e_get_flags(l1e) & _PAGE_RW )
{
rc = mem_sharing_unshare_page(pg_owner,
rc = mem_sharing_unshare_page(p2m_get_hostp2m(pg_owner),
l1e_get_pfn(l1e),
0);
if ( rc )
@@ -3475,12 +3477,12 @@ int do_mmu_update(
{
l2_pgentry_t l2e = l2e_from_intpte(req.val);
p2m_type_t l2e_p2mt;
gfn_to_mfn(pg_owner, l2e_get_pfn(l2e), &l2e_p2mt);
gfn_to_mfn(p2m_get_hostp2m(pg_owner), l2e_get_pfn(l2e), &l2e_p2mt);
if ( p2m_is_paged(l2e_p2mt) )
{
p2m_mem_paging_populate(pg_owner, l2e_get_pfn(l2e));
p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
l2e_get_pfn(l2e));
rc = -ENOENT;
break;
}
@@ -3505,12 +3507,12 @@ int do_mmu_update(
{
l3_pgentry_t l3e = l3e_from_intpte(req.val);
p2m_type_t l3e_p2mt;
gfn_to_mfn(pg_owner, l3e_get_pfn(l3e), &l3e_p2mt);
gfn_to_mfn(p2m_get_hostp2m(pg_owner), l3e_get_pfn(l3e), &l3e_p2mt);
if ( p2m_is_paged(l3e_p2mt) )
{
p2m_mem_paging_populate(pg_owner, l3e_get_pfn(l3e));
p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
l3e_get_pfn(l3e));
rc = -ENOENT;
break;
}
@@ -3536,12 +3538,13 @@ int do_mmu_update(
{
l4_pgentry_t l4e = l4e_from_intpte(req.val);
p2m_type_t l4e_p2mt;
gfn_to_mfn(pg_owner, l4e_get_pfn(l4e), &l4e_p2mt);
gfn_to_mfn(p2m_get_hostp2m(pg_owner),
l4e_get_pfn(l4e), &l4e_p2mt);
if ( p2m_is_paged(l4e_p2mt) )
{
p2m_mem_paging_populate(pg_owner, l4e_get_pfn(l4e));
p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
l4e_get_pfn(l4e));
rc = -ENOENT;
break;
}
@@ -3923,8 +3926,8 @@ static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame,
p2mt = p2m_grant_map_ro;
else
p2mt = p2m_grant_map_rw;
rc = guest_physmap_add_entry(current->domain, addr >> PAGE_SHIFT,
frame, 0, p2mt);
rc = guest_physmap_add_entry(p2m_get_hostp2m(current->domain),
addr >> PAGE_SHIFT, frame, 0, p2mt);
if ( rc )
return GNTST_general_error;
else
@@ -3962,11 +3965,12 @@ static int replace_grant_p2m_mapping(
unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
p2m_type_t type;
mfn_t old_mfn;
struct domain *d = current->domain;
if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
return GNTST_general_error;
old_mfn = gfn_to_mfn_current(gfn, &type);
old_mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &type);
if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame )
{
gdprintk(XENLOG_WARNING,
@@ -3974,7 +3978,7 @@ static int replace_grant_p2m_mapping(
type, mfn_x(old_mfn), frame);
return GNTST_general_error;
}
guest_physmap_remove_page(current->domain, gfn, frame, 0);
guest_physmap_remove_page(d, gfn, frame, 0);
return GNTST_okay;
}
@@ -4581,7 +4585,8 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
{
p2m_type_t p2mt;
xatp.idx = mfn_x(gfn_to_mfn_unshare(d, xatp.idx, &p2mt, 0));
xatp.idx = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d),
xatp.idx, &p2mt, 0));
/* If the page is still shared, exit early */
if ( p2m_is_shared(p2mt) )
{
@@ -4771,6 +4776,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
{
xen_pod_target_t target;
struct domain *d;
struct p2m_domain *p2m;
/* Support DOMID_SELF? */
if ( !IS_PRIV(current->domain) )
@@ -4794,9 +4800,10 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
rc = p2m_pod_set_mem_target(d, target.target_pages);
}
p2m = p2m_get_hostp2m(d);
target.tot_pages = d->tot_pages;
target.pod_cache_pages = d->arch.p2m->pod.count;
target.pod_entries = d->arch.p2m->pod.entry_count;
target.pod_cache_pages = p2m->pod.count;
target.pod_entries = p2m->pod.entry_count;
if ( copy_to_guest(arg, &target, 1) )
{
+8 -7
View File
@@ -86,17 +86,17 @@ static uint32_t set_ad_bits(void *guest_p, void *walk_p, int set_dirty)
return 0;
}
static inline void *map_domain_gfn(struct domain *d,
static inline void *map_domain_gfn(struct p2m_domain *p2m,
gfn_t gfn,
mfn_t *mfn,
p2m_type_t *p2mt,
uint32_t *rc)
{
/* Translate the gfn, unsharing if shared */
*mfn = gfn_to_mfn_unshare(d, gfn_x(gfn), p2mt, 0);
*mfn = gfn_to_mfn_unshare(p2m, gfn_x(gfn), p2mt, 0);
if ( p2m_is_paging(*p2mt) )
{
p2m_mem_paging_populate(d, gfn_x(gfn));
p2m_mem_paging_populate(p2m, gfn_x(gfn));
*rc = _PAGE_PAGED;
return NULL;
@@ -119,7 +119,8 @@ static inline void *map_domain_gfn(struct domain *d,
/* Walk the guest pagetables, after the manner of a hardware walker. */
uint32_t
guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
unsigned long va, walk_t *gw,
uint32_t pfec, mfn_t top_mfn, void *top_map)
{
struct domain *d = v->domain;
@@ -154,7 +155,7 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
if ( rc & _PAGE_PRESENT ) goto out;
/* Map the l3 table */
l3p = map_domain_gfn(d,
l3p = map_domain_gfn(p2m,
guest_l4e_get_gfn(gw->l4e),
&gw->l3mfn,
&p2mt,
@@ -181,7 +182,7 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
#endif /* PAE or 64... */
/* Map the l2 table */
l2p = map_domain_gfn(d,
l2p = map_domain_gfn(p2m,
guest_l3e_get_gfn(gw->l3e),
&gw->l2mfn,
&p2mt,
@@ -237,7 +238,7 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
else
{
/* Not a superpage: carry on and find the l1e. */
l1p = map_domain_gfn(d,
l1p = map_domain_gfn(p2m,
guest_l2e_get_gfn(gw->l2e),
&gw->l1mfn,
&p2mt,
+6 -6
View File
@@ -43,13 +43,14 @@ unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
void *top_map;
p2m_type_t p2mt;
walk_t gw;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
/* Get the top-level table's MFN */
cr3 = v->arch.hvm_vcpu.guest_cr[3];
top_mfn = gfn_to_mfn_unshare(v->domain, cr3 >> PAGE_SHIFT, &p2mt, 0);
top_mfn = gfn_to_mfn_unshare(p2m, cr3 >> PAGE_SHIFT, &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(v->domain, cr3 >> PAGE_SHIFT);
p2m_mem_paging_populate(p2m, cr3 >> PAGE_SHIFT);
pfec[0] = PFEC_page_paged;
return INVALID_GFN;
@@ -71,17 +72,17 @@ unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
#if GUEST_PAGING_LEVELS == 3
top_map += (cr3 & ~(PAGE_MASK | 31));
#endif
missing = guest_walk_tables(v, gva, &gw, pfec[0], top_mfn, top_map);
missing = guest_walk_tables(v, p2m, gva, &gw, pfec[0], top_mfn, top_map);
unmap_domain_page(top_map);
/* Interpret the answer */
if ( missing == 0 )
{
gfn_t gfn = guest_l1e_get_gfn(gw.l1e);
gfn_to_mfn_unshare(v->domain, gfn_x(gfn), &p2mt, 0);
gfn_to_mfn_unshare(p2m, gfn_x(gfn), &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(v->domain, gfn_x(gfn));
p2m_mem_paging_populate(p2m, gfn_x(gfn));
pfec[0] = PFEC_page_paged;
return INVALID_GFN;
@@ -130,4 +131,3 @@ unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
* indent-tabs-mode: nil
* End:
*/
+20 -14
View File
@@ -70,7 +70,7 @@ static int hap_enable_vram_tracking(struct domain *d)
/* set l1e entries of P2M table to be read-only. */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
@@ -90,7 +90,7 @@ static int hap_disable_vram_tracking(struct domain *d)
/* set l1e entries of P2M table with normal mode */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
p2m_change_type(d, i, p2m_ram_logdirty, p2m_ram_rw);
p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_logdirty, p2m_ram_rw);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
@@ -106,7 +106,7 @@ static void hap_clean_vram_tracking(struct domain *d)
/* set l1e entries of P2M table to be read-only. */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
}
@@ -200,7 +200,8 @@ static int hap_enable_log_dirty(struct domain *d)
hap_unlock(d);
/* set l1e entries of P2M table to be read-only. */
p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
p2m_change_entry_type_global(p2m_get_hostp2m(d),
p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
}
@@ -212,14 +213,16 @@ static int hap_disable_log_dirty(struct domain *d)
hap_unlock(d);
/* set l1e entries of P2M table with normal mode */
p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw);
p2m_change_entry_type_global(p2m_get_hostp2m(d),
p2m_ram_logdirty, p2m_ram_rw);
return 0;
}
static void hap_clean_dirty_bitmap(struct domain *d)
{
/* set l1e entries of P2M table to be read-only. */
p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
p2m_change_entry_type_global(p2m_get_hostp2m(d),
p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
}
@@ -273,8 +276,9 @@ static void hap_free(struct domain *d, mfn_t mfn)
page_list_add_tail(pg, &d->arch.paging.hap.freelist);
}
static struct page_info *hap_alloc_p2m_page(struct domain *d)
static struct page_info *hap_alloc_p2m_page(struct p2m_domain *p2m)
{
struct domain *d = p2m->domain;
struct page_info *pg;
hap_lock(d);
@@ -312,8 +316,9 @@ static struct page_info *hap_alloc_p2m_page(struct domain *d)
return pg;
}
static void hap_free_p2m_page(struct domain *d, struct page_info *pg)
static void hap_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
{
struct domain *d = p2m->domain;
hap_lock(d);
ASSERT(page_get_owner(pg) == d);
/* Should have just the one ref we gave it in alloc_p2m_page() */
@@ -594,7 +599,8 @@ int hap_enable(struct domain *d, u32 mode)
/* allocate P2m table */
if ( mode & PG_translate )
{
rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
rv = p2m_alloc_table(p2m_get_hostp2m(d),
hap_alloc_p2m_page, hap_free_p2m_page);
if ( rv != 0 )
goto out;
}
@@ -611,7 +617,7 @@ void hap_final_teardown(struct domain *d)
if ( d->arch.paging.hap.total_pages != 0 )
hap_teardown(d);
p2m_teardown(d);
p2m_teardown(p2m_get_hostp2m(d));
ASSERT(d->arch.paging.hap.p2m_pages == 0);
}
@@ -711,9 +717,11 @@ void hap_vcpu_init(struct vcpu *v)
static int hap_page_fault(struct vcpu *v, unsigned long va,
struct cpu_user_regs *regs)
{
struct domain *d = v->domain;
HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n",
v->domain->domain_id, v->vcpu_id);
domain_crash(v->domain);
d->domain_id, v->vcpu_id);
domain_crash(d);
return 0;
}
@@ -882,5 +890,3 @@ static const struct paging_mode hap_paging_long_mode = {
* indent-tabs-mode: nil
* End:
*/
+71 -61
View File
@@ -36,23 +36,23 @@
#define is_epte_superpage(ept_entry) ((ept_entry)->sp)
/* Non-ept "lock-and-check" wrapper */
static int ept_pod_check_and_populate(struct domain *d, unsigned long gfn,
static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,
ept_entry_t *entry, int order,
p2m_query_t q)
{
int r;
p2m_lock(d->arch.p2m);
p2m_lock(p2m);
/* Check to make sure this is still PoD */
if ( entry->avail1 != p2m_populate_on_demand )
{
p2m_unlock(d->arch.p2m);
p2m_unlock(p2m);
return 0;
}
r = p2m_pod_demand_populate(d, gfn, order, q);
r = p2m_pod_demand_populate(p2m, gfn, order, q);
p2m_unlock(d->arch.p2m);
p2m_unlock(p2m);
return r;
}
@@ -98,11 +98,11 @@ static void ept_p2m_type_to_flags(ept_entry_t *entry, p2m_type_t type)
#define GUEST_TABLE_POD_PAGE 3
/* Fill in middle levels of ept table */
static int ept_set_middle_entry(struct domain *d, ept_entry_t *ept_entry)
static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
{
struct page_info *pg;
pg = p2m_alloc_ptp(d, 0);
pg = p2m_alloc_ptp(p2m, 0);
if ( pg == NULL )
return 0;
@@ -119,7 +119,7 @@ static int ept_set_middle_entry(struct domain *d, ept_entry_t *ept_entry)
}
/* free ept sub tree behind an entry */
void ept_free_entry(struct domain *d, ept_entry_t *ept_entry, int level)
void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
{
/* End if the entry is a leaf entry. */
if ( level == 0 || !is_epte_present(ept_entry) ||
@@ -130,14 +130,14 @@ void ept_free_entry(struct domain *d, ept_entry_t *ept_entry, int level)
{
ept_entry_t *epte = map_domain_page(ept_entry->mfn);
for ( int i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
ept_free_entry(d, epte + i, level - 1);
ept_free_entry(p2m, epte + i, level - 1);
unmap_domain_page(epte);
}
d->arch.p2m->free_page(d, mfn_to_page(ept_entry->mfn));
p2m->free_page(p2m, mfn_to_page(ept_entry->mfn));
}
static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
static int ept_split_super_page(struct p2m_domain *p2m, ept_entry_t *ept_entry,
int level, int target)
{
ept_entry_t new_ept, *table;
@@ -150,7 +150,7 @@ static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
ASSERT(is_epte_superpage(ept_entry));
if ( !ept_set_middle_entry(d, &new_ept) )
if ( !ept_set_middle_entry(p2m, &new_ept) )
return 0;
table = map_domain_page(new_ept.mfn);
@@ -174,7 +174,7 @@ static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
ASSERT(is_epte_superpage(epte));
if ( !(rv = ept_split_super_page(d, epte, level - 1, target)) )
if ( !(rv = ept_split_super_page(p2m, epte, level - 1, target)) )
break;
}
@@ -200,7 +200,7 @@ static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
* GUEST_TABLE_POD:
* The next entry is marked populate-on-demand.
*/
static int ept_next_level(struct domain *d, bool_t read_only,
static int ept_next_level(struct p2m_domain *p2m, bool_t read_only,
ept_entry_t **table, unsigned long *gfn_remainder,
int next_level)
{
@@ -225,7 +225,7 @@ static int ept_next_level(struct domain *d, bool_t read_only,
if ( read_only )
return GUEST_TABLE_MAP_FAILED;
if ( !ept_set_middle_entry(d, ept_entry) )
if ( !ept_set_middle_entry(p2m, ept_entry) )
return GUEST_TABLE_MAP_FAILED;
}
@@ -245,7 +245,7 @@ static int ept_next_level(struct domain *d, bool_t read_only,
* by observing whether any gfn->mfn translations are modified.
*/
static int
ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int order, p2m_type_t p2mt)
{
ept_entry_t *table, *ept_entry;
@@ -259,6 +259,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
uint8_t ipat = 0;
int need_modify_vtd_table = 1;
int needs_sync = 1;
struct domain *d = p2m->domain;
/*
* the caller must make sure:
@@ -267,7 +268,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
* 3. passing a valid order.
*/
if ( ((gfn | mfn_x(mfn)) & ((1UL << order) - 1)) ||
(gfn >> ((ept_get_wl(d) + 1) * EPT_TABLE_ORDER)) ||
((u64)gfn >> ((ept_get_wl(d) + 1) * EPT_TABLE_ORDER)) ||
(order % EPT_TABLE_ORDER) )
return 0;
@@ -281,7 +282,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
for ( i = ept_get_wl(d); i > target; i-- )
{
ret = ept_next_level(d, 0, &table, &gfn_remainder, i);
ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i);
if ( !ret )
goto out;
else if ( ret != GUEST_TABLE_NORMAL_PAGE )
@@ -311,7 +312,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
(p2mt == p2m_ram_paging_in_start) )
{
ept_entry->emt = epte_get_entry_emt(d, gfn, mfn, &ipat,
ept_entry->emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat,
direct_mmio);
ept_entry->ipat = ipat;
ept_entry->sp = order ? 1 : 0;
@@ -337,9 +338,9 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
split_ept_entry = *ept_entry;
if ( !ept_split_super_page(d, &split_ept_entry, i, target) )
if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
{
ept_free_entry(d, &split_ept_entry, i);
ept_free_entry(p2m, &split_ept_entry, i);
goto out;
}
@@ -349,7 +350,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
/* then move to the level we want to make real changes */
for ( ; i > target; i-- )
ept_next_level(d, 0, &table, &gfn_remainder, i);
ept_next_level(p2m, 0, &table, &gfn_remainder, i);
ASSERT(i == target);
@@ -374,8 +375,8 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
/* Track the highest gfn for which we have ever had a valid mapping */
if ( mfn_valid(mfn_x(mfn)) &&
(gfn + (1UL << order) - 1 > d->arch.p2m->max_mapped_pfn) )
d->arch.p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
(gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
/* Success */
rv = 1;
@@ -384,10 +385,10 @@ out:
unmap_domain_page(table);
if ( needs_sync )
ept_sync_domain(d);
ept_sync_domain(p2m->domain);
/* Now the p2m table is not shared with vt-d page table */
if ( rv && iommu_enabled && need_iommu(d) && need_modify_vtd_table )
if ( rv && iommu_enabled && need_iommu(p2m->domain) && need_modify_vtd_table )
{
if ( p2mt == p2m_ram_rw )
{
@@ -395,22 +396,22 @@ out:
{
for ( i = 0; i < (1 << order); i++ )
iommu_map_page(
d, gfn - offset + i, mfn_x(mfn) - offset + i,
p2m->domain, gfn - offset + i, mfn_x(mfn) - offset + i,
IOMMUF_readable | IOMMUF_writable);
}
else if ( !order )
iommu_map_page(
d, gfn, mfn_x(mfn), IOMMUF_readable | IOMMUF_writable);
p2m->domain, gfn, mfn_x(mfn), IOMMUF_readable | IOMMUF_writable);
}
else
{
if ( order == EPT_TABLE_ORDER )
{
for ( i = 0; i < (1 << order); i++ )
iommu_unmap_page(d, gfn - offset + i);
iommu_unmap_page(p2m->domain, gfn - offset + i);
}
else if ( !order )
iommu_unmap_page(d, gfn);
iommu_unmap_page(p2m->domain, gfn);
}
}
@@ -418,9 +419,11 @@ out:
}
/* Read ept p2m entries */
static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
static mfn_t ept_get_entry(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
struct domain *d = p2m->domain;
ept_entry_t *table = map_domain_page(ept_get_asr(d));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
@@ -432,7 +435,7 @@ static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
*t = p2m_mmio_dm;
/* This pfn is higher than the highest the p2m map currently holds */
if ( gfn > d->arch.p2m->max_mapped_pfn )
if ( gfn > p2m->max_mapped_pfn )
goto out;
/* Should check if gfn obeys GAW here. */
@@ -440,7 +443,7 @@ static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
for ( i = ept_get_wl(d); i > 0; i-- )
{
retry:
ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret )
goto out;
else if ( ret == GUEST_TABLE_POD_PAGE )
@@ -457,7 +460,7 @@ static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
index = gfn_remainder >> ( i * EPT_TABLE_ORDER);
ept_entry = table + index;
if ( !ept_pod_check_and_populate(d, gfn,
if ( !ept_pod_check_and_populate(p2m, gfn,
ept_entry, 9, q) )
goto retry;
else
@@ -480,7 +483,7 @@ static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
ASSERT(i == 0);
if ( ept_pod_check_and_populate(d, gfn,
if ( ept_pod_check_and_populate(p2m, gfn,
ept_entry, 0, q) )
goto out;
}
@@ -511,9 +514,10 @@ out:
/* WARNING: Only caller doesn't care about PoD pages. So this function will
* always return 0 for PoD pages, not populate them. If that becomes necessary,
* pass a p2m_query_t type along to distinguish. */
static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn, int *level)
static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
unsigned long gfn, int *level)
{
ept_entry_t *table = map_domain_page(ept_get_asr(d));
ept_entry_t *table = map_domain_page(ept_get_asr(p2m->domain));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
ept_entry_t content = { .epte = 0 };
@@ -522,12 +526,12 @@ static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn, in
int ret=0;
/* This pfn is higher than the highest the p2m map currently holds */
if ( gfn > d->arch.p2m->max_mapped_pfn )
if ( gfn > p2m->max_mapped_pfn )
goto out;
for ( i = ept_get_wl(d); i > 0; i-- )
for ( i = ept_get_wl(p2m->domain); i > 0; i-- )
{
ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret || ret == GUEST_TABLE_POD_PAGE )
goto out;
else if ( ret == GUEST_TABLE_SUPER_PAGE )
@@ -546,6 +550,7 @@ static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn, in
void ept_walk_table(struct domain *d, unsigned long gfn)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
ept_entry_t *table = map_domain_page(ept_get_asr(d));
unsigned long gfn_remainder = gfn;
@@ -555,10 +560,10 @@ void ept_walk_table(struct domain *d, unsigned long gfn)
d->domain_id, gfn);
/* This pfn is higher than the highest the p2m map currently holds */
if ( gfn > d->arch.p2m->max_mapped_pfn )
if ( gfn > p2m->max_mapped_pfn )
{
gdprintk(XENLOG_ERR, " gfn exceeds max_mapped_pfn %lx\n",
d->arch.p2m->max_mapped_pfn);
p2m->max_mapped_pfn);
goto out;
}
@@ -593,17 +598,18 @@ out:
return;
}
static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t,
static mfn_t ept_get_entry_current(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
return ept_get_entry(current->domain, gfn, t, q);
return ept_get_entry(p2m, gfn, t, q);
}
/*
* To test if the new emt type is the same with old,
* return 1 to not to reset ept entry.
*/
static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
static int need_modify_ept_entry(struct p2m_domain *p2m, unsigned long gfn,
mfn_t mfn, uint8_t o_ipat, uint8_t o_emt,
p2m_type_t p2mt)
{
@@ -611,7 +617,7 @@ static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
uint8_t emt;
bool_t direct_mmio = (p2mt == p2m_mmio_direct);
emt = epte_get_entry_emt(d, gfn, mfn, &ipat, direct_mmio);
emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat, direct_mmio);
if ( (emt == o_emt) && (ipat == o_ipat) )
return 0;
@@ -619,21 +625,23 @@ static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
return 1;
}
void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
void ept_change_entry_emt_with_range(struct domain *d,
unsigned long start_gfn,
unsigned long end_gfn)
{
unsigned long gfn;
ept_entry_t e;
mfn_t mfn;
int order = 0;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_lock(d->arch.p2m);
p2m_lock(p2m);
for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
{
int level = 0;
uint64_t trunk = 0;
e = ept_get_entry_content(d, gfn, &level);
e = ept_get_entry_content(p2m, gfn, &level);
if ( !p2m_has_emt(e.avail1) )
continue;
@@ -652,9 +660,9 @@ void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
* Set emt for super page.
*/
order = level * EPT_TABLE_ORDER;
if ( need_modify_ept_entry(d, gfn, mfn,
if ( need_modify_ept_entry(p2m, gfn, mfn,
e.ipat, e.emt, e.avail1) )
ept_set_entry(d, gfn, mfn, order, e.avail1);
ept_set_entry(p2m, gfn, mfn, order, e.avail1);
gfn += trunk;
break;
}
@@ -663,11 +671,11 @@ void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
}
else /* gfn assigned with 4k */
{
if ( need_modify_ept_entry(d, gfn, mfn, e.ipat, e.emt, e.avail1) )
ept_set_entry(d, gfn, mfn, order, e.avail1);
if ( need_modify_ept_entry(p2m, gfn, mfn, e.ipat, e.emt, e.avail1) )
ept_set_entry(p2m, gfn, mfn, order, e.avail1);
}
}
p2m_unlock(d->arch.p2m);
p2m_unlock(p2m);
}
/*
@@ -701,9 +709,10 @@ static void ept_change_entry_type_page(mfn_t ept_page_mfn, int ept_page_level,
unmap_domain_page(epte);
}
static void ept_change_entry_type_global(struct domain *d,
static void ept_change_entry_type_global(struct p2m_domain *p2m,
p2m_type_t ot, p2m_type_t nt)
{
struct domain *d = p2m->domain;
if ( ept_get_asr(d) == 0 )
return;
@@ -714,10 +723,11 @@ static void ept_change_entry_type_global(struct domain *d,
void ept_p2m_init(struct domain *d)
{
d->arch.p2m->set_entry = ept_set_entry;
d->arch.p2m->get_entry = ept_get_entry;
d->arch.p2m->get_entry_current = ept_get_entry_current;
d->arch.p2m->change_entry_type_global = ept_change_entry_type_global;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m->set_entry = ept_set_entry;
p2m->get_entry = ept_get_entry;
p2m->get_entry_current = ept_get_entry_current;
p2m->change_entry_type_global = ept_change_entry_type_global;
}
static void ept_dump_p2m_table(unsigned char key)
@@ -742,7 +752,7 @@ static void ept_dump_p2m_table(unsigned char key)
p2m = p2m_get_hostp2m(d);
printk("\ndomain%d EPT p2m table: \n", d->domain_id);
for ( gfn = 0; gfn <= d->arch.p2m->max_mapped_pfn; gfn += (1 << order) )
for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += (1 << order) )
{
gfn_remainder = gfn;
mfn = _mfn(INVALID_MFN);
@@ -750,7 +760,7 @@ static void ept_dump_p2m_table(unsigned char key)
for ( i = ept_get_wl(d); i > 0; i-- )
{
ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( ret != GUEST_TABLE_NORMAL_PAGE )
break;
}
+2 -2
View File
@@ -235,7 +235,7 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
/* Get MFN of ring page */
guest_get_eff_l1e(v, ring_addr, &l1e);
gfn = l1e_get_pfn(l1e);
ring_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
ring_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn, &p2mt);
rc = -EINVAL;
if ( unlikely(!mfn_valid(mfn_x(ring_mfn))) )
@@ -244,7 +244,7 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
/* Get MFN of shared page */
guest_get_eff_l1e(v, shared_addr, &l1e);
gfn = l1e_get_pfn(l1e);
shared_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
shared_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn, &p2mt);
rc = -EINVAL;
if ( unlikely(!mfn_valid(mfn_x(shared_mfn))) )
+5 -4
View File
@@ -29,33 +29,34 @@ int mem_paging_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
XEN_GUEST_HANDLE(void) u_domctl)
{
int rc;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
switch( mec->op )
{
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE:
{
unsigned long gfn = mec->gfn;
rc = p2m_mem_paging_nominate(d, gfn);
rc = p2m_mem_paging_nominate(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT:
{
unsigned long gfn = mec->gfn;
rc = p2m_mem_paging_evict(d, gfn);
rc = p2m_mem_paging_evict(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP:
{
unsigned long gfn = mec->gfn;
rc = p2m_mem_paging_prep(d, gfn);
rc = p2m_mem_paging_prep(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME:
{
p2m_mem_paging_resume(d);
p2m_mem_paging_resume(p2m);
rc = 0;
}
break;
+17 -12
View File
@@ -251,6 +251,7 @@ static void mem_sharing_audit(void)
list_for_each(le, &e->gfns)
{
struct domain *d;
struct p2m_domain *p2m;
p2m_type_t t;
mfn_t mfn;
@@ -262,7 +263,8 @@ static void mem_sharing_audit(void)
g->domain, g->gfn, mfn_x(e->mfn));
continue;
}
mfn = gfn_to_mfn(d, g->gfn, &t);
p2m = p2m_get_hostp2m(d);
mfn = gfn_to_mfn(p2m, g->gfn, &t);
if(mfn_x(mfn) != mfn_x(e->mfn))
MEM_SHARING_DEBUG("Incorrect P2M for d=%d, PFN=%lx."
"Expecting MFN=%ld, got %ld\n",
@@ -377,7 +379,7 @@ int mem_sharing_debug_gfn(struct domain *d, unsigned long gfn)
mfn_t mfn;
struct page_info *page;
mfn = gfn_to_mfn(d, gfn, &p2mt);
mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &p2mt);
page = mfn_to_page(mfn);
printk("Debug for domain=%d, gfn=%lx, ",
@@ -487,7 +489,7 @@ int mem_sharing_debug_gref(struct domain *d, grant_ref_t ref)
return mem_sharing_debug_gfn(d, gfn);
}
int mem_sharing_nominate_page(struct domain *d,
int mem_sharing_nominate_page(struct p2m_domain *p2m,
unsigned long gfn,
int expected_refcnt,
shr_handle_t *phandle)
@@ -499,10 +501,11 @@ int mem_sharing_nominate_page(struct domain *d,
shr_handle_t handle;
shr_hash_entry_t *hash_entry;
struct gfn_info *gfn_info;
struct domain *d = p2m->domain;
*phandle = 0UL;
mfn = gfn_to_mfn(d, gfn, &p2mt);
mfn = gfn_to_mfn(p2m, gfn, &p2mt);
/* Check if mfn is valid */
ret = -EINVAL;
@@ -536,7 +539,7 @@ int mem_sharing_nominate_page(struct domain *d,
}
/* Change the p2m type */
if(p2m_change_type(d, gfn, p2mt, p2m_ram_shared) != p2mt)
if(p2m_change_type(p2m, gfn, p2mt, p2m_ram_shared) != p2mt)
{
/* This is unlikely, as the type must have changed since we've checked
* it a few lines above.
@@ -599,7 +602,7 @@ int mem_sharing_share_pages(shr_handle_t sh, shr_handle_t ch)
list_del(&gfn->list);
d = get_domain_by_id(gfn->domain);
BUG_ON(!d);
BUG_ON(set_shared_p2m_entry(d, gfn->gfn, se->mfn) == 0);
BUG_ON(set_shared_p2m_entry(p2m_get_hostp2m(d), gfn->gfn, se->mfn) == 0);
put_domain(d);
list_add(&gfn->list, &se->gfns);
put_page_and_type(cpage);
@@ -618,7 +621,7 @@ err_out:
return ret;
}
int mem_sharing_unshare_page(struct domain *d,
int mem_sharing_unshare_page(struct p2m_domain *p2m,
unsigned long gfn,
uint16_t flags)
{
@@ -631,8 +634,9 @@ int mem_sharing_unshare_page(struct domain *d,
struct gfn_info *gfn_info = NULL;
shr_handle_t handle;
struct list_head *le;
struct domain *d = p2m->domain;
mfn = gfn_to_mfn(d, gfn, &p2mt);
mfn = gfn_to_mfn(p2m, gfn, &p2mt);
page = mfn_to_page(mfn);
handle = page->shr_handle;
@@ -696,7 +700,7 @@ gfn_found:
unmap_domain_page(s);
unmap_domain_page(t);
ASSERT(set_shared_p2m_entry(d, gfn, page_to_mfn(page)) != 0);
ASSERT(set_shared_p2m_entry(p2m, gfn, page_to_mfn(page)) != 0);
put_page_and_type(old_page);
private_page_found:
@@ -708,7 +712,7 @@ private_page_found:
atomic_dec(&nr_saved_mfns);
shr_unlock();
if(p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) !=
if(p2m_change_type(p2m, gfn, p2m_ram_shared, p2m_ram_rw) !=
p2m_ram_shared)
{
printk("Could not change p2m type.\n");
@@ -740,7 +744,7 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec)
shr_handle_t handle;
if(!mem_sharing_enabled(d))
return -EINVAL;
rc = mem_sharing_nominate_page(d, gfn, 0, &handle);
rc = mem_sharing_nominate_page(p2m_get_hostp2m(d), gfn, 0, &handle);
mec->u.nominate.handle = handle;
mem_sharing_audit();
}
@@ -756,7 +760,8 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec)
return -EINVAL;
if(mem_sharing_gref_to_gfn(d, gref, &gfn) < 0)
return -EINVAL;
rc = mem_sharing_nominate_page(d, gfn, 3, &handle);
rc = mem_sharing_nominate_page(p2m_get_hostp2m(d),
gfn, 3, &handle);
mec->u.nominate.handle = handle;
mem_sharing_audit();
}
+336 -326
View File
File diff suppressed because it is too large. Load diff
+20 -14
View File
@@ -1714,8 +1714,9 @@ sh_alloc_p2m_pages(struct domain *d)
// Returns 0 if no memory is available...
static struct page_info *
shadow_alloc_p2m_page(struct domain *d)
shadow_alloc_p2m_page(struct p2m_domain *p2m)
{
struct domain *d = p2m->domain;
struct page_info *pg;
mfn_t mfn;
void *p;
@@ -1741,8 +1742,9 @@ shadow_alloc_p2m_page(struct domain *d)
}
static void
shadow_free_p2m_page(struct domain *d, struct page_info *pg)
shadow_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
{
struct domain *d = p2m->domain;
ASSERT(page_get_owner(pg) == d);
/* Should have just the one ref we gave it in alloc_p2m_page() */
if ( (pg->count_info & PGC_count_mask) != 1 )
@@ -3100,6 +3102,7 @@ int shadow_enable(struct domain *d, u32 mode)
struct page_info *pg = NULL;
uint32_t *e;
int i, rv = 0;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
mode |= PG_SH_enable;
@@ -3135,7 +3138,8 @@ int shadow_enable(struct domain *d, u32 mode)
* to avoid possible deadlock. */
if ( mode & PG_translate )
{
rv = p2m_alloc_table(d, shadow_alloc_p2m_page, shadow_free_p2m_page);
rv = p2m_alloc_table(p2m,
shadow_alloc_p2m_page, shadow_free_p2m_page);
if (rv != 0)
goto out_unlocked;
}
@@ -3146,7 +3150,7 @@ int shadow_enable(struct domain *d, u32 mode)
{
/* Get a single page from the shadow pool. Take it via the
* P2M interface to make freeing it simpler afterwards. */
pg = shadow_alloc_p2m_page(d);
pg = shadow_alloc_p2m_page(p2m);
if ( pg == NULL )
{
rv = -ENOMEM;
@@ -3195,10 +3199,10 @@ int shadow_enable(struct domain *d, u32 mode)
out_locked:
shadow_unlock(d);
out_unlocked:
if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m_get_hostp2m(d))) )
p2m_teardown(d);
if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) )
p2m_teardown(p2m);
if ( rv != 0 && pg != NULL )
shadow_free_p2m_page(d, pg);
shadow_free_p2m_page(p2m, pg);
domain_unpause(d);
return rv;
}
@@ -3210,6 +3214,7 @@ void shadow_teardown(struct domain *d)
struct vcpu *v;
mfn_t mfn;
struct page_info *pg;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
ASSERT(d->is_dying);
ASSERT(d != current->domain);
@@ -3264,7 +3269,7 @@ void shadow_teardown(struct domain *d)
#endif /* (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) */
while ( (pg = page_list_remove_head(&d->arch.paging.shadow.p2m_freelist)) )
shadow_free_p2m_page(d, pg);
shadow_free_p2m_page(p2m, pg);
if ( d->arch.paging.shadow.total_pages != 0 )
{
@@ -3298,7 +3303,7 @@ void shadow_teardown(struct domain *d)
if ( !hvm_paging_enabled(v) )
v->arch.guest_table = pagetable_null();
}
shadow_free_p2m_page(d,
shadow_free_p2m_page(p2m,
pagetable_get_page(d->arch.paging.shadow.unpaged_pagetable));
d->arch.paging.shadow.unpaged_pagetable = pagetable_null();
}
@@ -3335,7 +3340,7 @@ void shadow_final_teardown(struct domain *d)
shadow_teardown(d);
/* It is now safe to pull down the p2m map. */
p2m_teardown(d);
p2m_teardown(p2m_get_hostp2m(d));
SHADOW_PRINTK("dom %u final teardown done."
" Shadow pages total = %u, free = %u, p2m=%u\n",
@@ -3657,10 +3662,11 @@ int shadow_track_dirty_vram(struct domain *d,
unsigned long i;
p2m_type_t t;
struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
if (end_pfn < begin_pfn
|| begin_pfn > d->arch.p2m->max_mapped_pfn
|| end_pfn >= d->arch.p2m->max_mapped_pfn)
|| begin_pfn > p2m->max_mapped_pfn
|| end_pfn >= p2m->max_mapped_pfn)
return -EINVAL;
shadow_lock(d);
@@ -3729,7 +3735,7 @@ int shadow_track_dirty_vram(struct domain *d,
/* Iterate over VRAM to track dirty bits. */
for ( i = 0; i < nr; i++ ) {
mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
mfn_t mfn = gfn_to_mfn(p2m, begin_pfn + i, &t);
struct page_info *page;
int dirty = 0;
paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3814,7 +3820,7 @@ int shadow_track_dirty_vram(struct domain *d,
/* was clean for more than two seconds, try to disable guest
* write access */
for ( i = begin_pfn; i < end_pfn; i++ ) {
mfn_t mfn = gfn_to_mfn(d, i, &t);
mfn_t mfn = gfn_to_mfn(p2m, i, &t);
if (mfn_x(mfn) != INVALID_MFN)
flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn, 1, 0);
}
+28 -21
View File
@@ -167,7 +167,7 @@ static inline uint32_t
sh_walk_guest_tables(struct vcpu *v, unsigned long va, walk_t *gw,
uint32_t pfec)
{
return guest_walk_tables(v, va, gw, pfec,
return guest_walk_tables(v, p2m_get_hostp2m(v->domain), va, gw, pfec,
#if GUEST_PAGING_LEVELS == 3 /* PAE */
_mfn(INVALID_MFN),
v->arch.paging.shadow.gl3e
@@ -2240,6 +2240,7 @@ static int validate_gl4e(struct vcpu *v, void *new_ge, mfn_t sl4mfn, void *se)
shadow_l4e_t *sl4p = se;
mfn_t sl3mfn = _mfn(INVALID_MFN);
struct domain *d = v->domain;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_type_t p2mt;
int result = 0;
@@ -2248,7 +2249,7 @@ static int validate_gl4e(struct vcpu *v, void *new_ge, mfn_t sl4mfn, void *se)
if ( guest_l4e_get_flags(new_gl4e) & _PAGE_PRESENT )
{
gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
mfn_t gl3mfn = gfn_to_mfn_query(d, gl3gfn, &p2mt);
mfn_t gl3mfn = gfn_to_mfn_query(p2m, gl3gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2299,13 +2300,14 @@ static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
mfn_t sl2mfn = _mfn(INVALID_MFN);
p2m_type_t p2mt;
int result = 0;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
perfc_incr(shadow_validate_gl3e_calls);
if ( guest_l3e_get_flags(new_gl3e) & _PAGE_PRESENT )
{
gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
mfn_t gl2mfn = gfn_to_mfn_query(v->domain, gl2gfn, &p2mt);
mfn_t gl2mfn = gfn_to_mfn_query(p2m, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2329,6 +2331,7 @@ static int validate_gl2e(struct vcpu *v, void *new_ge, mfn_t sl2mfn, void *se)
guest_l2e_t new_gl2e = *(guest_l2e_t *)new_ge;
shadow_l2e_t *sl2p = se;
mfn_t sl1mfn = _mfn(INVALID_MFN);
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
int result = 0;
@@ -2354,7 +2357,7 @@ static int validate_gl2e(struct vcpu *v, void *new_ge, mfn_t sl2mfn, void *se)
}
else
{
mfn_t gl1mfn = gfn_to_mfn_query(v->domain, gl1gfn, &p2mt);
mfn_t gl1mfn = gfn_to_mfn_query(p2m, gl1gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2415,6 +2418,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se)
shadow_l1e_t *sl1p = se;
gfn_t gfn;
mfn_t gmfn;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
int result = 0;
#if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
@@ -2424,7 +2428,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se)
perfc_incr(shadow_validate_gl1e_calls);
gfn = guest_l1e_get_gfn(new_gl1e);
gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
gmfn = gfn_to_mfn_query(p2m, gfn, &p2mt);
l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
result |= shadow_set_l1e(v, sl1p, new_sl1e, p2mt, sl1mfn);
@@ -2484,7 +2488,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t gl1mfn, mfn_t snpmfn)
shadow_l1e_t nsl1e;
gfn = guest_l1e_get_gfn(gl1e);
gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
rc |= shadow_set_l1e(v, sl1p, nsl1e, p2mt, sl1mfn);
@@ -2810,7 +2814,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw,
/* Look at the gfn that the l1e is pointing at */
gfn = guest_l1e_get_gfn(gl1e);
gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
/* Propagate the entry. */
l1e_propagate_from_guest(v, gl1e, gmfn, &sl1e, ft_prefetch, p2mt);
@@ -3166,7 +3170,7 @@ static int sh_page_fault(struct vcpu *v,
/* What mfn is the guest trying to access? */
gfn = guest_l1e_get_gfn(gw.l1e);
gmfn = gfn_to_mfn_guest(d, gfn, &p2mt);
gmfn = gfn_to_mfn_guest(p2m_get_hostp2m(d), gfn, &p2mt);
if ( shadow_mode_refcounts(d) &&
((!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ||
@@ -4272,7 +4276,7 @@ sh_update_cr3(struct vcpu *v, int do_locking)
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
flush |= sh_remove_write_access(v, gl2mfn, 2, 0);
}
@@ -4285,7 +4289,7 @@ sh_update_cr3(struct vcpu *v, int do_locking)
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
? SH_type_l2h_shadow
@@ -4682,7 +4686,7 @@ static void sh_pagetable_dying(struct vcpu *v, paddr_t gpa)
if ( gcr3 == gpa )
fast_path = 1;
gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >> PAGE_SHIFT), &p2mt);
if ( !mfn_valid(gmfn) || !p2m_is_ram(p2mt) )
{
printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid %"PRIpaddr"\n",
@@ -4702,7 +4706,7 @@ static void sh_pagetable_dying(struct vcpu *v, paddr_t gpa)
{
/* retrieving the l2s */
gl2a = guest_l3e_get_paddr(gl3e[i]);
gmfn = gfn_to_mfn_query(v->domain, _gfn(gl2a >> PAGE_SHIFT), &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gl2a >> PAGE_SHIFT), &p2mt);
smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_pae_shadow);
}
@@ -4737,7 +4741,7 @@ static void sh_pagetable_dying(struct vcpu *v, paddr_t gpa)
shadow_lock(v->domain);
gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >> PAGE_SHIFT), &p2mt);
#if GUEST_PAGING_LEVELS == 2
smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_32_shadow);
#else
@@ -4777,6 +4781,7 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v,
mfn_t mfn;
p2m_type_t p2mt;
uint32_t pfec = PFEC_page_present | PFEC_write_access;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
/* Translate the VA to a GFN */
gfn = sh_gva_to_gfn(v, vaddr, &pfec);
@@ -4792,9 +4797,9 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v,
/* Translate the GFN to an MFN */
/* PoD: query only if shadow lock is held (to avoid deadlock) */
if ( shadow_locked_by_me(v->domain) )
mfn = gfn_to_mfn_query(v->domain, _gfn(gfn), &p2mt);
mfn = gfn_to_mfn_query(p2m, _gfn(gfn), &p2mt);
else
mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
mfn = gfn_to_mfn(p2m, _gfn(gfn), &p2mt);
if ( p2m_is_readonly(p2mt) )
return _mfn(READONLY_GFN);
@@ -5199,7 +5204,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn, mfn_t x)
{
gfn = guest_l1e_get_gfn(*gl1e);
mfn = shadow_l1e_get_mfn(*sl1e);
gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
if ( !p2m_is_grant(p2mt) && mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
" --> %" PRI_mfn " != mfn %" PRI_mfn,
@@ -5243,6 +5248,7 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
shadow_l2e_t *sl2e;
mfn_t mfn, gmfn, gl2mfn;
gfn_t gfn;
struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
char *s;
int done = 0;
@@ -5269,7 +5275,7 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
mfn = shadow_l2e_get_mfn(*sl2e);
gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
? get_fl1_shadow_status(v, gfn)
: get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
: get_shadow_status(v, gfn_to_mfn_query(p2m, gfn, &p2mt),
SH_type_l1_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
@@ -5277,8 +5283,8 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
" --> %" PRI_mfn " != mfn %" PRI_mfn,
gfn_x(gfn),
(guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
: mfn_x(gfn_to_mfn_query(v->domain, gfn, &p2mt)),
mfn_x(gmfn), mfn_x(mfn));
: mfn_x(gfn_to_mfn_query(p2m,
gfn, &p2mt)), mfn_x(gmfn), mfn_x(mfn));
}
});
sh_unmap_domain_page(gp);
@@ -5316,7 +5322,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x)
{
gfn = guest_l3e_get_gfn(*gl3e);
mfn = shadow_l3e_get_mfn(*sl3e);
gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
gmfn = get_shadow_status(v, gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt),
((GUEST_PAGING_LEVELS == 3 ||
is_pv_32on64_vcpu(v))
&& !shadow_mode_external(v->domain)
@@ -5363,7 +5369,8 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x)
{
gfn = guest_l4e_get_gfn(*gl4e);
mfn = shadow_l4e_get_mfn(*sl4e);
gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, &p2mt),
gmfn = get_shadow_status(v, gfn_to_mfn_query(p2m_get_hostp2m(v->domain),
gfn, &p2mt),
SH_type_l3_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
+2
View File
@@ -28,6 +28,7 @@
#include "op_x86_model.h"
struct op_counter_config counter_config[OP_MAX_COUNTER];
struct op_ibs_config ibs_config;
static struct op_x86_model_spec const *__read_mostly model;
static struct op_msrs cpu_msrs[NR_CPUS];
@@ -430,6 +431,7 @@ static int __init nmi_init(void)
case 0x10:
model = &op_athlon_spec;
cpu_type = "x86-64/family10";
ibs_caps = ibs_init();
break;
case 0x11:
model = &op_athlon_spec;
+12
View File
@@ -26,4 +26,16 @@ struct op_counter_config {
extern struct op_counter_config counter_config[];
/* AMD IBS configuration */
struct op_ibs_config {
unsigned long op_enabled;
unsigned long fetch_enabled;
unsigned long max_cnt_fetch;
unsigned long max_cnt_op;
unsigned long rand_en;
unsigned long dispatched_ops;
};
extern struct op_ibs_config ibs_config;
#endif /* OP_COUNTER_H */
+348
View File
@@ -19,6 +19,7 @@
#include <asm/regs.h>
#include <asm/current.h>
#include <asm/hvm/support.h>
#include <xen/pci_regs.h>
#include "op_x86_model.h"
#include "op_counter.h"
@@ -47,6 +48,116 @@ static unsigned long reset_value[NUM_COUNTERS];
extern char svm_stgi_label[];
u32 ibs_caps = 0;
static u64 ibs_op_ctl;
/* IBS cpuid feature detection */
#define IBS_CPUID_FEATURES 0x8000001b
/* IBS MSRs */
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
#define MSR_AMD64_IBSOPCTL 0xc0011033
#define MSR_AMD64_IBSOPRIP 0xc0011034
#define MSR_AMD64_IBSOPDATA 0xc0011035
#define MSR_AMD64_IBSOPDATA2 0xc0011036
#define MSR_AMD64_IBSOPDATA3 0xc0011037
#define MSR_AMD64_IBSDCLINAD 0xc0011038
#define MSR_AMD64_IBSDCPHYSAD 0xc0011039
#define MSR_AMD64_IBSCTL 0xc001103a
/*
* Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
* bit 0 is used to indicate the existence of IBS.
*/
#define IBS_CAPS_AVAIL (1LL<<0)
#define IBS_CAPS_RDWROPCNT (1LL<<3)
#define IBS_CAPS_OPCNT (1LL<<4)
/* IBS randomization macros */
#define IBS_RANDOM_BITS 12
#define IBS_RANDOM_MASK ((1ULL << IBS_RANDOM_BITS) - 1)
#define IBS_RANDOM_MAXCNT_OFFSET (1ULL << (IBS_RANDOM_BITS - 5))
/* IbsFetchCtl bits/masks */
#define IBS_FETCH_RAND_EN (1ULL<<57)
#define IBS_FETCH_VAL (1ULL<<49)
#define IBS_FETCH_ENABLE (1ULL<<48)
#define IBS_FETCH_CNT 0xFFFF0000ULL
#define IBS_FETCH_MAX_CNT 0x0000FFFFULL
/* IbsOpCtl bits */
#define IBS_OP_CNT_CTL (1ULL<<19)
#define IBS_OP_VAL (1ULL<<18)
#define IBS_OP_ENABLE (1ULL<<17)
#define IBS_OP_MAX_CNT 0x0000FFFFULL
/* IBS sample identifier */
#define IBS_FETCH_CODE 13
#define IBS_OP_CODE 14
#define clamp(val, min, max) ({ \
typeof(val) __val = (val); \
typeof(min) __min = (min); \
typeof(max) __max = (max); \
(void) (&__val == &__min); \
(void) (&__val == &__max); \
__val = __val < __min ? __min: __val; \
__val > __max ? __max: __val; })
/*
* 16-bit Linear Feedback Shift Register (LFSR)
*/
static unsigned int lfsr_random(void)
{
static unsigned int lfsr_value = 0xF00D;
unsigned int bit;
/* Compute next bit to shift in */
bit = ((lfsr_value >> 0) ^
(lfsr_value >> 2) ^
(lfsr_value >> 3) ^
(lfsr_value >> 5)) & 0x0001;
/* Advance to next register value */
lfsr_value = (lfsr_value >> 1) | (bit << 15);
return lfsr_value;
}
/*
* IBS software randomization
*
* The IBS periodic op counter is randomized in software. The lower 12
* bits of the 20 bit counter are randomized. IbsOpCurCnt is
* initialized with a 12 bit random value.
*/
static inline u64 op_amd_randomize_ibs_op(u64 val)
{
unsigned int random = lfsr_random();
if (!(ibs_caps & IBS_CAPS_RDWROPCNT))
/*
* Work around if the hw can not write to IbsOpCurCnt
*
* Randomize the lower 8 bits of the 16 bit
* IbsOpMaxCnt [15:0] value in the range of -128 to
* +127 by adding/subtracting an offset to the
* maximum count (IbsOpMaxCnt).
*
* To avoid over or underflows and protect upper bits
* starting at bit 16, the initial value for
* IbsOpMaxCnt must fit in the range from 0x0081 to
* 0xff80.
*/
val += (s8)(random >> 4);
else
val |= (u64)(random & IBS_RANDOM_MASK) << 32;
return val;
}
static void athlon_fill_in_addresses(struct op_msrs * const msrs)
{
msrs->counters[0].addr = MSR_K7_PERFCTR0;
@@ -101,6 +212,78 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
}
}
static inline void
ibs_log_event(u64 data, struct cpu_user_regs * const regs, int mode)
{
struct vcpu *v = current;
u32 temp = 0;
temp = data & 0xFFFFFFFF;
xenoprof_log_event(v, regs, temp, mode, 0);
temp = (data >> 32) & 0xFFFFFFFF;
xenoprof_log_event(v, regs, temp, mode, 0);
}
static inline int handle_ibs(int mode, struct cpu_user_regs * const regs)
{
u64 val, ctl;
struct vcpu *v = current;
if (!ibs_caps)
return 1;
if (ibs_config.fetch_enabled) {
rdmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
if (ctl & IBS_FETCH_VAL) {
rdmsrl(MSR_AMD64_IBSFETCHLINAD, val);
xenoprof_log_event(v, regs, IBS_FETCH_CODE, mode, 0);
xenoprof_log_event(v, regs, val, mode, 0);
ibs_log_event(val, regs, mode);
ibs_log_event(ctl, regs, mode);
rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, val);
ibs_log_event(val, regs, mode);
/* reenable the IRQ */
ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
ctl |= IBS_FETCH_ENABLE;
wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
}
}
if (ibs_config.op_enabled) {
rdmsrl(MSR_AMD64_IBSOPCTL, ctl);
if (ctl & IBS_OP_VAL) {
rdmsrl(MSR_AMD64_IBSOPRIP, val);
xenoprof_log_event(v, regs, IBS_OP_CODE, mode, 0);
xenoprof_log_event(v, regs, val, mode, 0);
ibs_log_event(val, regs, mode);
rdmsrl(MSR_AMD64_IBSOPDATA, val);
ibs_log_event(val, regs, mode);
rdmsrl(MSR_AMD64_IBSOPDATA2, val);
ibs_log_event(val, regs, mode);
rdmsrl(MSR_AMD64_IBSOPDATA3, val);
ibs_log_event(val, regs, mode);
rdmsrl(MSR_AMD64_IBSDCLINAD, val);
ibs_log_event(val, regs, mode);
rdmsrl(MSR_AMD64_IBSDCPHYSAD, val);
ibs_log_event(val, regs, mode);
/* reenable the IRQ */
ctl = op_amd_randomize_ibs_op(ibs_op_ctl);
wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
}
}
return 1;
}
static int athlon_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
struct cpu_user_regs * const regs)
@@ -134,10 +317,51 @@ static int athlon_check_ctrs(unsigned int const cpu,
}
}
ovf = handle_ibs(mode, regs);
/* See op_model_ppro.c */
return ovf;
}
static inline void start_ibs(void)
{
u64 val = 0;
if (!ibs_caps)
return;
if (ibs_config.fetch_enabled) {
val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT;
val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
val |= IBS_FETCH_ENABLE;
wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
}
if (ibs_config.op_enabled) {
ibs_op_ctl = ibs_config.max_cnt_op >> 4;
if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) {
/*
* IbsOpCurCnt not supported. See
* op_amd_randomize_ibs_op() for details.
*/
ibs_op_ctl = clamp((unsigned long long)ibs_op_ctl,
0x0081ULL, 0xFF80ULL);
} else {
/*
* The start value is randomized with a
* positive offset, we need to compensate it
* with the half of the randomized range. Also
* avoid underflows.
*/
ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
IBS_OP_MAX_CNT);
}
if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
ibs_op_ctl |= IBS_OP_CNT_CTL;
ibs_op_ctl |= IBS_OP_ENABLE;
val = op_amd_randomize_ibs_op(ibs_op_ctl);
wrmsrl(MSR_AMD64_IBSOPCTL, val);
}
}
static void athlon_start(struct op_msrs const * const msrs)
{
@@ -150,8 +374,22 @@ static void athlon_start(struct op_msrs const * const msrs)
CTRL_WRITE(msr_content, msrs, i);
}
}
start_ibs();
}
static void stop_ibs(void)
{
if (!ibs_caps)
return;
if (ibs_config.fetch_enabled)
/* clear max count and enable */
wrmsrl(MSR_AMD64_IBSFETCHCTL, 0);
if (ibs_config.op_enabled)
/* clear max count and enable */
wrmsrl(MSR_AMD64_IBSOPCTL, 0);
}
static void athlon_stop(struct op_msrs const * const msrs)
{
@@ -165,8 +403,118 @@ static void athlon_stop(struct op_msrs const * const msrs)
CTRL_SET_INACTIVE(msr_content);
CTRL_WRITE(msr_content, msrs, i);
}
stop_ibs();
}
#define IBSCTL_LVTOFFSETVAL (1 << 8)
#define APIC_EILVT_MSG_NMI 0x4
#define APIC_EILVT_LVTOFF_IBS 1
#define APIC_EILVTn(n) (0x500 + 0x10 * n)
static inline void init_ibs_nmi_per_cpu(void *arg)
{
unsigned long reg;
reg = (APIC_EILVT_LVTOFF_IBS << 4) + APIC_EILVTn(0);
apic_write(reg, APIC_EILVT_MSG_NMI << 8);
}
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203
#define IBSCTL 0x1cc
static int init_ibs_nmi(void)
{
int bus, dev, func;
u32 id, value;
u16 vendor_id, dev_id;
int nodes;
/* per CPU setup */
on_each_cpu(init_ibs_nmi_per_cpu, NULL, 1);
nodes = 0;
for (bus = 0; bus < 256; bus++) {
for (dev = 0; dev < 32; dev++) {
for (func = 0; func < 8; func++) {
id = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
if ((id == 0xffffffff) || (id == 0x00000000) ||
(id == 0x0000ffff) || (id == 0xffff0000))
continue;
vendor_id = id & 0xffff;
dev_id = (id >> 16) & 0xffff;
if ((vendor_id == PCI_VENDOR_ID_AMD) &&
(dev_id == PCI_DEVICE_ID_AMD_10H_NB_MISC)) {
pci_conf_write32(bus, dev, func, IBSCTL,
IBSCTL_LVTOFFSETVAL | APIC_EILVT_LVTOFF_IBS);
value = pci_conf_read32(bus, dev, func, IBSCTL);
if (value != (IBSCTL_LVTOFFSETVAL |
APIC_EILVT_LVTOFF_IBS)) {
printk("Xenoprofile: Failed to setup IBS LVT offset, "
"IBSCTL = 0x%08x", value);
return 1;
}
nodes++;
}
}
}
}
if (!nodes) {
printk("Xenoprofile: No CPU node configured for IBS");
return 1;
}
return 0;
}
static u32 get_ibs_caps(void)
{
#ifdef CONFIG_X86_32
return 0;
#else
unsigned int max_level;
if (!boot_cpu_has(X86_FEATURE_IBS))
return 0;
/* check IBS cpuid feature flags */
max_level = cpuid_eax(0x80000000);
if (max_level < IBS_CPUID_FEATURES)
return IBS_CAPS_AVAIL;
ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
if (!(ibs_caps & IBS_CAPS_AVAIL))
/* cpuid flags not valid */
return IBS_CAPS_AVAIL;
return ibs_caps;
#endif
}
u32 ibs_init(void)
{
u32 ibs_caps = 0;
ibs_caps = get_ibs_caps();
if ( !ibs_caps )
return 0;
if (init_ibs_nmi()) {
ibs_caps = 0;
return 0;
}
printk("Xenoprofile: AMD IBS detected (0x%08x)\n",
(unsigned)ibs_caps);
return ibs_caps;
}
struct op_x86_model_spec const op_athlon_spec = {
.num_counters = NUM_COUNTERS,
+17
View File
@@ -38,6 +38,23 @@ int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg)
return 0;
}
int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_ibs_counter ibs_counter;
if ( copy_from_guest(&ibs_counter, arg, 1) )
return -EFAULT;
ibs_config.op_enabled = ibs_counter.op_enabled;
ibs_config.fetch_enabled = ibs_counter.fetch_enabled;
ibs_config.max_cnt_fetch = ibs_counter.max_cnt_fetch;
ibs_config.max_cnt_op = ibs_counter.max_cnt_op;
ibs_config.rand_en = ibs_counter.rand_en;
ibs_config.dispatched_ops = ibs_counter.dispatched_ops;
return 0;
}
#ifdef CONFIG_COMPAT
int compat_oprof_arch_counter(XEN_GUEST_HANDLE(void) arg)
{
+56 -2
View File
@@ -205,6 +205,58 @@ void __devinit srat_detect_node(int cpu)
printk("CPU %d APIC %d -> Node %d\n", cpu, apicid, node);
}
/*
* Sort CPUs by <node,package,core,thread> tuple. Fortunately this hierarchy is
* reflected in the structure of modern APIC identifiers, so we sort based on
* those. This is slightly complicated by the fact that the BSP must remain
* CPU 0. Hence we do a variation on longest-prefix matching to do the best we
* can while keeping CPU 0 static.
*/
static void __init normalise_cpu_order(void)
{
unsigned int i, j, min_cpu;
uint32_t apicid, diff, min_diff;
for_each_present_cpu ( i )
{
apicid = x86_cpu_to_apicid[i];
min_diff = min_cpu = ~0u;
/*
* Find remaining CPU with longest-prefix match on APIC ID.
* Among identical longest-prefix matches, pick the smallest APIC ID.
*/
for ( j = next_cpu(i, cpu_present_map);
j < NR_CPUS;
j = next_cpu(j, cpu_present_map) )
{
diff = x86_cpu_to_apicid[j] ^ apicid;
while ( diff & (diff-1) )
diff &= diff-1;
if ( (diff < min_diff) ||
((diff == min_diff) &&
(x86_cpu_to_apicid[j] < x86_cpu_to_apicid[min_cpu])) )
{
min_diff = diff;
min_cpu = j;
}
}
/* If no match then there must be no CPUs remaining to consider. */
if ( min_cpu >= NR_CPUS )
{
BUG_ON(next_cpu(i, cpu_present_map) < NR_CPUS);
break;
}
/* Switch the best-matching CPU with the next CPU in logical order. */
j = next_cpu(i, cpu_present_map);
apicid = x86_cpu_to_apicid[min_cpu];
x86_cpu_to_apicid[min_cpu] = x86_cpu_to_apicid[j];
x86_cpu_to_apicid[j] = apicid;
}
}
/*
* Ensure a given physical memory range is present in the bootstrap mappings.
* Use superpage mappings to ensure that pagetable memory needn't be allocated.
@@ -952,8 +1004,6 @@ void __init __start_xen(unsigned long mbi_p)
acpi_boot_init();
init_cpu_to_node();
if ( smp_found_config )
get_smp_config();
@@ -964,6 +1014,10 @@ void __init __start_xen(unsigned long mbi_p)
init_apic_mappings();
normalise_cpu_order();
init_cpu_to_node();
if ( x2apic_is_available() )
enable_x2apic();
+1 -1
View File
@@ -264,7 +264,7 @@ process_mce:
ALIGN
/* %ebx: struct vcpu */
process_nmi:
cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%ebx)
testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%ebx)
jnz test_guest_events
sti
movb $0,VCPU_nmi_pending(%ebx)
+1 -1
View File
@@ -137,7 +137,7 @@ compat_process_mce:
ALIGN
/* %rbx: struct vcpu */
compat_process_nmi:
cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
jnz compat_test_guest_events
sti
movb $0,VCPU_nmi_pending(%rbx)
+1 -1
View File
@@ -239,7 +239,7 @@ process_mce:
ALIGN
/* %rbx: struct vcpu */
process_nmi:
cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
jnz test_guest_events
sti
movb $0,VCPU_nmi_pending(%rbx)
+25
View File
@@ -191,6 +191,8 @@ struct vcpu *alloc_vcpu(
/* Must be called after making new vcpu visible to for_each_vcpu(). */
vcpu_check_shutdown(v);
domain_update_node_affinity(d);
return v;
}
@@ -235,6 +237,8 @@ struct domain *domain_create(
INIT_PAGE_LIST_HEAD(&d->page_list);
INIT_PAGE_LIST_HEAD(&d->xenpage_list);
spin_lock_init(&d->node_affinity_lock);
spin_lock_init(&d->shutdown_lock);
d->shutdown_code = -1;
@@ -341,6 +345,27 @@ struct domain *domain_create(
}
void domain_update_node_affinity(struct domain *d)
{
cpumask_t cpumask = CPU_MASK_NONE;
nodemask_t nodemask = NODE_MASK_NONE;
struct vcpu *v;
unsigned int node;
spin_lock(&d->node_affinity_lock);
for_each_vcpu ( d, v )
cpus_or(cpumask, cpumask, v->cpu_affinity);
for_each_online_node ( node )
if ( cpus_intersects(node_to_cpumask(node), cpumask) )
node_set(node, nodemask);
d->node_affinity = nodemask;
spin_unlock(&d->node_affinity_lock);
}
struct domain *get_domain_by_id(domid_t dom)
{
struct domain *d;
+7 -5
View File
@@ -109,7 +109,7 @@ static unsigned inline int max_nr_maptrack_frames(void)
#define gfn_to_mfn_private(_d, _gfn) ({ \
p2m_type_t __p2mt; \
unsigned long __x; \
__x = mfn_x(gfn_to_mfn_unshare(_d, _gfn, &__p2mt, 1)); \
__x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt, 1)); \
if ( !p2m_is_valid(__p2mt) ) \
__x = INVALID_MFN; \
__x; })
@@ -1933,12 +1933,13 @@ __gnttab_copy(
{
#ifdef CONFIG_X86
p2m_type_t p2mt;
s_frame = mfn_x(gfn_to_mfn(sd, op->source.u.gmfn, &p2mt));
struct p2m_domain *p2m = p2m_get_hostp2m(sd);
s_frame = mfn_x(gfn_to_mfn(p2m, op->source.u.gmfn, &p2mt));
if ( !p2m_is_valid(p2mt) )
s_frame = INVALID_MFN;
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(sd, op->source.u.gmfn);
p2m_mem_paging_populate(p2m, op->source.u.gmfn);
rc = -ENOENT;
goto error_out;
}
@@ -1979,12 +1980,13 @@ __gnttab_copy(
{
#ifdef CONFIG_X86
p2m_type_t p2mt;
d_frame = mfn_x(gfn_to_mfn_unshare(dd, op->dest.u.gmfn, &p2mt, 1));
struct p2m_domain *p2m = p2m_get_hostp2m(dd);
d_frame = mfn_x(gfn_to_mfn_unshare(p2m, op->dest.u.gmfn, &p2mt, 1));
if ( !p2m_is_valid(p2mt) )
d_frame = INVALID_MFN;
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(dd, op->dest.u.gmfn);
p2m_mem_paging_populate(p2m, op->dest.u.gmfn);
rc = -ENOENT;
goto error_out;
}
+5 -8
View File
@@ -161,7 +161,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
unsigned long mfn;
#ifdef CONFIG_X86
mfn = mfn_x(gfn_to_mfn(d, gmfn, &p2mt));
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(d), gmfn, &p2mt));
#else
mfn = gmfn_to_mfn(d, gmfn);
#endif
@@ -259,7 +259,7 @@ static long memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg)
unsigned long in_chunk_order, out_chunk_order;
xen_pfn_t gpfn, gmfn, mfn;
unsigned long i, j, k;
unsigned int node, memflags = 0;
unsigned int memflags = 0;
long rc = 0;
struct domain *d;
struct page_info *page;
@@ -324,10 +324,7 @@ static long memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg)
d,
XENMEMF_get_address_bits(exch.out.mem_flags) ? :
(BITS_PER_LONG+PAGE_SHIFT)));
node = XENMEMF_get_node(exch.out.mem_flags);
if ( node == NUMA_NO_NODE )
node = domain_to_node(d);
memflags |= MEMF_node(node);
memflags |= MEMF_node(XENMEMF_get_node(exch.out.mem_flags));
for ( i = (exch.nr_exchanged >> in_chunk_order);
i < (exch.in.nr_extents >> in_chunk_order);
@@ -359,7 +356,7 @@ static long memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg)
p2m_type_t p2mt;
/* Shared pages cannot be exchanged */
mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn + k, &p2mt, 0));
mfn = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d), gmfn + k, &p2mt, 0));
if ( p2m_is_shared(p2mt) )
{
rc = -ENOMEM;
@@ -545,7 +542,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
}
args.memflags |= MEMF_node(XENMEMF_get_node(reservation.mem_flags));
if (reservation.mem_flags & XENMEMF_exact_node_request)
if ( reservation.mem_flags & XENMEMF_exact_node_request )
args.memflags |= MEMF_exact_node;
if ( op == XENMEM_populate_physmap
+47 -21
View File
@@ -295,20 +295,29 @@ static unsigned long init_node_heap(int node, unsigned long mfn,
/* Allocate 2^@order contiguous pages. */
static struct page_info *alloc_heap_pages(
unsigned int zone_lo, unsigned int zone_hi,
unsigned int node, unsigned int order, unsigned int memflags)
unsigned int order, unsigned int memflags,
struct domain *d)
{
unsigned int i, j, zone = 0;
unsigned int num_nodes = num_online_nodes();
unsigned int first_node, i, j, zone = 0, nodemask_retry = 0;
unsigned int node = (uint8_t)((memflags >> _MEMF_node) - 1);
unsigned long request = 1UL << order;
bool_t exact_node_request = !!(memflags & MEMF_exact_node);
cpumask_t extra_cpus_mask, mask;
struct page_info *pg;
nodemask_t nodemask = (d != NULL ) ? d->node_affinity : node_online_map;
if ( node == NUMA_NO_NODE )
{
node = cpu_to_node(smp_processor_id());
exact_node_request = 0;
memflags &= ~MEMF_exact_node;
if ( d != NULL )
{
node = next_node(d->last_alloc_node, nodemask);
if ( node >= MAX_NUMNODES )
node = first_node(nodemask);
}
if ( node >= MAX_NUMNODES )
node = cpu_to_node(smp_processor_id());
}
first_node = node;
ASSERT(node >= 0);
ASSERT(zone_lo <= zone_hi);
@@ -335,7 +344,7 @@ static struct page_info *alloc_heap_pages(
* zone before failing, only calc new node value if we fail to find memory
* in target node, this avoids needless computation on fast-path.
*/
for ( i = 0; i < num_nodes; i++ )
for ( ; ; )
{
zone = zone_hi;
do {
@@ -349,18 +358,35 @@ static struct page_info *alloc_heap_pages(
goto found;
} while ( zone-- > zone_lo ); /* careful: unsigned zone may wrap */
if ( exact_node_request )
if ( memflags & MEMF_exact_node )
goto not_found;
/* Pick next node, wrapping around if needed. */
node = next_node(node, node_online_map);
if (node == MAX_NUMNODES)
node = first_node(node_online_map);
/* Pick next node. */
if ( !node_isset(node, nodemask) )
{
/* Very first node may be caller-specified and outside nodemask. */
ASSERT(!nodemask_retry);
first_node = node = first_node(nodemask);
if ( node < MAX_NUMNODES )
continue;
}
else if ( (node = next_node(node, nodemask)) >= MAX_NUMNODES )
node = first_node(nodemask);
if ( node == first_node )
{
/* When we have tried all in nodemask, we fall back to others. */
if ( nodemask_retry++ )
goto not_found;
nodes_andnot(nodemask, node_online_map, nodemask);
first_node = node = first_node(nodemask);
if ( node >= MAX_NUMNODES )
goto not_found;
}
}
try_tmem:
/* Try to free memory from tmem */
if ( (pg = tmem_relinquish_pages(order,memflags)) != NULL )
if ( (pg = tmem_relinquish_pages(order, memflags)) != NULL )
{
/* reassigning an already allocated anonymous heap page */
spin_unlock(&heap_lock);
@@ -386,6 +412,9 @@ static struct page_info *alloc_heap_pages(
total_avail_pages -= request;
ASSERT(total_avail_pages >= 0);
if ( d != NULL )
d->last_alloc_node = node;
spin_unlock(&heap_lock);
cpus_clear(mask);
@@ -1010,7 +1039,7 @@ void *alloc_xenheap_pages(unsigned int order, unsigned int memflags)
ASSERT(!in_irq());
pg = alloc_heap_pages(MEMZONE_XEN, MEMZONE_XEN,
cpu_to_node(smp_processor_id()), order, memflags);
order, memflags, NULL);
if ( unlikely(pg == NULL) )
return NULL;
@@ -1153,24 +1182,21 @@ struct page_info *alloc_domheap_pages(
{
struct page_info *pg = NULL;
unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
unsigned int node = (uint8_t)((memflags >> _MEMF_node) - 1), dma_zone;
unsigned int dma_zone;
ASSERT(!in_irq());
if ( (node == NUMA_NO_NODE) && (d != NULL) )
node = domain_to_node(d);
bits = domain_clamp_alloc_bitsize(d, bits ? : (BITS_PER_LONG+PAGE_SHIFT));
if ( (zone_hi = min_t(unsigned int, bits_to_zone(bits), zone_hi)) == 0 )
return NULL;
if ( dma_bitsize && ((dma_zone = bits_to_zone(dma_bitsize)) < zone_hi) )
pg = alloc_heap_pages(dma_zone + 1, zone_hi, node, order, memflags);
pg = alloc_heap_pages(dma_zone + 1, zone_hi, order, memflags, d);
if ( (pg == NULL) &&
((memflags & MEMF_no_dma) ||
((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi,
node, order, memflags)) == NULL)) )
((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi, order,
memflags, d)) == NULL)) )
return NULL;
if ( (d != NULL) && assign_pages(d, pg, order, memflags) )
+42 -2
View File
@@ -64,7 +64,8 @@
/*
* Flags
*/
#define CSCHED_FLAG_VCPU_PARKED 0x0001 /* VCPU over capped credits */
#define CSCHED_FLAG_VCPU_PARKED 0x0001 /* VCPU over capped credits */
#define CSCHED_FLAG_VCPU_YIELD 0x0002 /* VCPU yielding */
/*
@@ -107,6 +108,12 @@
#endif /* CSCHED_STATS */
/*
* Boot parameters
*/
int sched_credit_default_yield = 0;
boolean_param("sched_credit_default_yield", sched_credit_default_yield);
/*
* Physical CPU
*/
@@ -202,6 +209,18 @@ __runq_insert(unsigned int cpu, struct csched_vcpu *svc)
break;
}
/* If the vcpu yielded, try to put it behind one lower-priority
* runnable vcpu if we can. The next runq_sort will bring it forward
* within 30ms if the queue too long. */
if ( svc->flags & CSCHED_FLAG_VCPU_YIELD
&& __runq_elem(iter)->pri > CSCHED_PRI_IDLE )
{
iter=iter->next;
/* Some sanity checks */
BUG_ON(iter == runq);
}
list_add_tail(&svc->runq_elem, iter);
}
@@ -748,6 +767,18 @@ csched_vcpu_wake(const struct scheduler *ops, struct vcpu *vc)
__runq_tickle(cpu, svc);
}
static void
csched_vcpu_yield(const struct scheduler *ops, struct vcpu *vc)
{
struct csched_vcpu * const sv = CSCHED_VCPU(vc);
if ( !sched_credit_default_yield )
{
/* Let the scheduler know that this vcpu is trying to yield */
sv->flags |= CSCHED_FLAG_VCPU_YIELD;
}
}
static int
csched_dom_cntl(
const struct scheduler *ops,
@@ -1069,7 +1100,9 @@ csched_acct(void* dummy)
if ( credit > CSCHED_CREDITS_PER_TSLICE )
{
__csched_vcpu_acct_stop_locked(prv, svc);
credit = 0;
/* Divide credits in half, so that when it starts
* accounting again, it starts a little bit "ahead" */
credit /= 2;
atomic_set(&svc->credit, credit);
}
}
@@ -1281,6 +1314,12 @@ csched_schedule(
snext->pri = CSCHED_PRI_TS_BOOST;
}
/*
* Clear YIELD flag before scheduling out
*/
if ( scurr->flags & CSCHED_FLAG_VCPU_YIELD )
scurr->flags &= ~(CSCHED_FLAG_VCPU_YIELD);
/*
* SMP Load balance:
*
@@ -1509,6 +1548,7 @@ const struct scheduler sched_credit_def = {
.sleep = csched_vcpu_sleep,
.wake = csched_vcpu_wake,
.yield = csched_vcpu_yield,
.adjust = csched_dom_cntl,
+18 -1
View File
@@ -276,6 +276,7 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
new_p = cycle_cpu(new_p, c->cpu_valid);
}
domain_update_node_affinity(d);
d->cpupool = c;
SCHED_OP(DOM2OP(d), free_domdata, d->sched_priv);
@@ -457,6 +458,7 @@ int cpu_disable_scheduler(unsigned int cpu)
struct vcpu *v;
struct cpupool *c;
int ret = 0;
bool_t affinity_broken;
c = per_cpu(cpupool, cpu);
if ( c == NULL )
@@ -467,6 +469,8 @@ int cpu_disable_scheduler(unsigned int cpu)
if ( d->cpupool != c )
continue;
affinity_broken = 0;
for_each_vcpu ( d, v )
{
vcpu_schedule_lock_irq(v);
@@ -477,6 +481,7 @@ int cpu_disable_scheduler(unsigned int cpu)
printk("Breaking vcpu affinity for domain %d vcpu %d\n",
v->domain->domain_id, v->vcpu_id);
cpus_setall(v->cpu_affinity);
affinity_broken = 1;
}
if ( v->processor == cpu )
@@ -499,7 +504,11 @@ int cpu_disable_scheduler(unsigned int cpu)
if ( v->processor == cpu )
ret = -EAGAIN;
}
if ( affinity_broken )
domain_update_node_affinity(d);
}
return ret;
}
@@ -525,6 +534,8 @@ int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity)
vcpu_schedule_unlock_irq(v);
domain_update_node_affinity(v->domain);
if ( test_bit(_VPF_migrating, &v->pause_flags) )
{
vcpu_sleep_nosync(v);
@@ -631,6 +642,12 @@ static long do_poll(struct sched_poll *sched_poll)
/* Voluntarily yield the processor for this allocation. */
static long do_yield(void)
{
struct vcpu * v=current;
vcpu_schedule_lock_irq(v);
SCHED_OP(VCPU2OP(v), yield, v);
vcpu_schedule_unlock_irq(v);
TRACE_2D(TRC_SCHED_YIELD, current->domain->domain_id, current->vcpu_id);
raise_softirq(SCHEDULE_SOFTIRQ);
return 0;
@@ -1296,7 +1313,7 @@ void schedule_cpu_switch(unsigned int cpu, struct cpupool *c)
spin_unlock_irqrestore(per_cpu(schedule_data, cpu).schedule_lock, flags);
SCHED_OP(old_ops, free_vdata, vpriv);
SCHED_OP(old_ops, free_vdata, vpriv_old);
SCHED_OP(old_ops, free_pdata, ppriv_old, cpu);
}
+1 -1
View File
@@ -100,7 +100,7 @@ static inline void *cli_mfn_to_va(tmem_cli_mfn_t cmfn, unsigned long *pcli_mfn)
unsigned long cli_mfn;
p2m_type_t t;
cli_mfn = mfn_x(gfn_to_mfn(current->domain, cmfn, &t));
cli_mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(current->domain), cmfn, &t));
if (t != p2m_ram_rw || cli_mfn == INVALID_MFN)
return NULL;
if (pcli_mfn != NULL)
+14
View File
@@ -881,6 +881,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
ret = -EFAULT;
break;
case XENOPROF_ibs_counter:
if ( (xenoprof_state != XENOPROF_COUNTERS_RESERVED) ||
(adomains == 0) )
{
ret = -EPERM;
break;
}
ret = xenoprof_arch_ibs_counter(arg);
break;
case XENOPROF_get_ibs_caps:
ret = ibs_caps;
break;
default:
ret = -ENOSYS;
}
+9 -2
View File
@@ -440,14 +440,21 @@ void io_apic_write_remap_rte(
{
*IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
*(IO_APIC_BASE(apic)+4) = value;
/* Recover the original value of 'mask' bit */
if ( rte_upper )
{
*IO_APIC_BASE(apic) = reg;
*(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);
}
return;
}
/* write new entry to ioapic */
*IO_APIC_BASE(apic) = reg;
*(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);
*IO_APIC_BASE(apic) = reg + 1;
*(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1);
*IO_APIC_BASE(apic) = reg;
*(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);
}
#if defined(__i386__) || defined(__x86_64__)
+7
View File
@@ -34,6 +34,13 @@ void xenoprof_arch_stop(void);
void xenoprof_arch_disable_virq(void);
void xenoprof_arch_release_counters(void);
static inline int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg)
{
return -ENOSYS; /* not supported */
}
/* AMD IBS not supported */
#define ibs_caps 0
struct vcpu;
struct cpu_user_regs;
int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
+2 -2
View File
@@ -272,8 +272,8 @@ guest_walk_to_gpa(walk_t *gw)
#define guest_walk_tables GPT_RENAME(guest_walk_tables, GUEST_PAGING_LEVELS)
extern uint32_t
guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
uint32_t pfec, mfn_t top_mfn, void *top_map);
guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map);
/* Pretty-print the contents of a guest-walk */
static inline void print_gw(walk_t *gw)
+3 -3
View File
@@ -30,17 +30,17 @@
typedef uint64_t shr_handle_t;
unsigned int mem_sharing_get_nr_saved_mfns(void);
int mem_sharing_nominate_page(struct domain *d,
int mem_sharing_nominate_page(struct p2m_domain *p2m,
unsigned long gfn,
int expected_refcnt,
shr_handle_t *phandle);
#define MEM_SHARING_MUST_SUCCEED (1<<0)
#define MEM_SHARING_DESTROY_GFN (1<<1)
int mem_sharing_unshare_page(struct domain *d,
int mem_sharing_unshare_page(struct p2m_domain *p2m,
unsigned long gfn,
uint16_t flags);
int mem_sharing_sharing_resume(struct domain *d);
int mem_sharing_cache_resize(struct domain *d, int new_size);
int mem_sharing_cache_resize(struct p2m_domain *p2m, int new_size);
int mem_sharing_domctl(struct domain *d,
xen_domctl_mem_sharing_op_t *mec);
void mem_sharing_init(void);
+67 -53
View File
@@ -172,23 +172,28 @@ struct p2m_domain {
/* Shadow translated domain: p2m mapping */
pagetable_t phys_table;
struct domain *domain; /* back pointer to domain */
/* Pages used to construct the p2m */
struct page_list_head pages;
/* Functions to call to get or free pages for the p2m */
struct page_info * (*alloc_page )(struct domain *d);
void (*free_page )(struct domain *d,
struct page_info * (*alloc_page )(struct p2m_domain *p2m);
void (*free_page )(struct p2m_domain *p2m,
struct page_info *pg);
int (*set_entry )(struct domain *d, unsigned long gfn,
int (*set_entry )(struct p2m_domain *p2m,
unsigned long gfn,
mfn_t mfn, unsigned int page_order,
p2m_type_t p2mt);
mfn_t (*get_entry )(struct domain *d, unsigned long gfn,
mfn_t (*get_entry )(struct p2m_domain *p2m,
unsigned long gfn,
p2m_type_t *p2mt,
p2m_query_t q);
mfn_t (*get_entry_current)(unsigned long gfn,
mfn_t (*get_entry_current)(struct p2m_domain *p2m,
unsigned long gfn,
p2m_type_t *p2mt,
p2m_query_t q);
void (*change_entry_type_global)(struct domain *d,
void (*change_entry_type_global)(struct p2m_domain *p2m,
p2m_type_t ot,
p2m_type_t nt);
@@ -279,65 +284,64 @@ static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
}
/* Read the current domain's p2m table. Do not populate PoD pages. */
static inline mfn_t gfn_to_mfn_type_current(unsigned long gfn, p2m_type_t *t,
static inline mfn_t gfn_to_mfn_type_current(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
return current->domain->arch.p2m->get_entry_current(gfn, t, q);
return p2m->get_entry_current(p2m, gfn, t, q);
}
/* Read another domain's P2M table, mapping pages as we go.
/* Read P2M table, mapping pages as we go.
* Do not populate PoD pages. */
static inline
mfn_t gfn_to_mfn_type_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
static inline mfn_t
gfn_to_mfn_type_p2m(struct p2m_domain *p2m, unsigned long gfn,
p2m_type_t *t, p2m_query_t q)
{
return d->arch.p2m->get_entry(d, gfn, t, q);
return p2m->get_entry(p2m, gfn, t, q);
}
/* General conversion function from gfn to mfn */
static inline mfn_t _gfn_to_mfn_type(struct domain *d,
static inline mfn_t _gfn_to_mfn_type(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
if ( !paging_mode_translate(d) )
if ( !p2m || !paging_mode_translate(p2m->domain) )
{
/* Not necessarily true, but for non-translated guests, we claim
* it's the most generic kind of memory */
*t = p2m_ram_rw;
return _mfn(gfn);
}
if ( likely(current->domain == d) )
return gfn_to_mfn_type_current(gfn, t, q);
if ( likely(current->domain == p2m->domain) )
return gfn_to_mfn_type_current(p2m, gfn, t, q);
else
return gfn_to_mfn_type_foreign(d, gfn, t, q);
return gfn_to_mfn_type_p2m(p2m, gfn, t, q);
}
#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_alloc)
#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_query)
#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_guest)
#define gfn_to_mfn(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), p2m_alloc)
#define gfn_to_mfn_query(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), p2m_query)
#define gfn_to_mfn_guest(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), p2m_guest)
#define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
#define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), p2m_alloc)
static inline mfn_t gfn_to_mfn_unshare(struct domain *d,
static inline mfn_t gfn_to_mfn_unshare(struct p2m_domain *p2m,
unsigned long gfn,
p2m_type_t *p2mt,
int must_succeed)
{
mfn_t mfn;
mfn = gfn_to_mfn(d, gfn, p2mt);
mfn = gfn_to_mfn(p2m, gfn, p2mt);
#ifdef __x86_64__
if ( p2m_is_shared(*p2mt) )
{
if ( mem_sharing_unshare_page(d, gfn,
if ( mem_sharing_unshare_page(p2m, gfn,
must_succeed
? MEM_SHARING_MUST_SUCCEED : 0) )
{
BUG_ON(must_succeed);
return mfn;
}
mfn = gfn_to_mfn(d, gfn, p2mt);
mfn = gfn_to_mfn(p2m, gfn, p2mt);
}
#endif
@@ -350,7 +354,7 @@ static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
{
mfn_t mfn;
p2m_type_t t;
mfn = gfn_to_mfn(d, gpfn, &t);
mfn = gfn_to_mfn(d->arch.p2m, gpfn, &t);
if ( p2m_is_valid(t) )
return mfn_x(mfn);
return INVALID_MFN;
@@ -374,16 +378,16 @@ int p2m_init(struct domain *d);
* build the p2m, and to release it again at the end of day.
*
* Returns 0 for success or -errno. */
int p2m_alloc_table(struct domain *d,
struct page_info * (*alloc_page)(struct domain *d),
void (*free_page)(struct domain *d, struct page_info *pg));
int p2m_alloc_table(struct p2m_domain *p2m,
struct page_info * (*alloc_page)(struct p2m_domain *p2m),
void (*free_page)(struct p2m_domain *p2m, struct page_info *pg));
/* Return all the p2m resources to Xen. */
void p2m_teardown(struct domain *d);
void p2m_teardown(struct p2m_domain *p2m);
void p2m_final_teardown(struct domain *d);
/* Dump PoD information about the domain */
void p2m_pod_dump_data(struct domain *d);
void p2m_pod_dump_data(struct p2m_domain *p2m);
/* Move all pages from the populate-on-demand cache to the domain page_list
* (usually in preparation for domain destruction) */
@@ -402,15 +406,19 @@ p2m_pod_decrease_reservation(struct domain *d,
/* Called by p2m code when demand-populating a PoD page */
int
p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
unsigned int order,
p2m_query_t q);
/* Add a page to a domain's p2m table */
int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
int guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
p2m_type_t t);
/* Remove a page from a domain's p2m table */
void guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order);
/* Set a p2m range as populate-on-demand */
int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
unsigned int order);
@@ -419,49 +427,55 @@ int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
*
* Return 0 for success
*/
static inline int guest_physmap_add_page(struct domain *d, unsigned long gfn,
static inline int guest_physmap_add_page(struct domain *d,
unsigned long gfn,
unsigned long mfn,
unsigned int page_order)
{
return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
return guest_physmap_add_entry(d->arch.p2m, gfn, mfn, page_order, p2m_ram_rw);
}
/* Remove a page from a domain's p2m table */
void guest_physmap_remove_page(struct domain *d, unsigned long gfn,
unsigned long mfn, unsigned int page_order);
static inline void guest_physmap_remove_page(struct domain *d,
unsigned long gfn,
unsigned long mfn, unsigned int page_order)
{
guest_physmap_remove_entry(d->arch.p2m, gfn, mfn, page_order);
}
/* Change types across all p2m entries in a domain */
void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt);
void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt);
void p2m_change_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t nt);
void p2m_change_entry_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t nt);
/* Compare-exchange the type of a single p2m entry */
p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn,
p2m_type_t ot, p2m_type_t nt);
/* Set mmio addresses in the p2m table (for pass-through) */
int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn);
int set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
int clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn);
#ifdef __x86_64__
/* Modify p2m table for shared gfn */
int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
int set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
/* Check if a nominated gfn is valid to be paged out */
int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn);
int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn);
/* Evict a frame */
int p2m_mem_paging_evict(struct domain *d, unsigned long gfn);
int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn);
/* Start populating a paged out frame */
void p2m_mem_paging_populate(struct domain *d, unsigned long gfn);
void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn);
/* Prepare the p2m for paging a frame in */
int p2m_mem_paging_prep(struct domain *d, unsigned long gfn);
int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn);
/* Resume normal operation (in case a domain was paused) */
void p2m_mem_paging_resume(struct domain *d);
void p2m_mem_paging_resume(struct p2m_domain *p2m);
#else
static inline void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
static inline void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{ }
#endif
struct page_info *p2m_alloc_ptp(struct domain *d, unsigned long type);
struct page_info *p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type);
#endif /* _XEN_P2M_H */
+5
View File
@@ -42,10 +42,15 @@ int xenoprof_arch_init(int *num_events, char *cpu_type);
int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
int compat_oprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg);
struct vcpu;
struct cpu_user_regs;
/* AMD IBS support */
u32 ibs_init(void);
extern u32 ibs_caps;
int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
static inline int xenoprof_backtrace_supported(void)
+15 -1
View File
@@ -50,7 +50,11 @@
#define XENOPROF_shutdown 13
#define XENOPROF_get_buffer 14
#define XENOPROF_set_backtrace 15
#define XENOPROF_last_op 15
/* AMD IBS support */
#define XENOPROF_get_ibs_caps 16
#define XENOPROF_ibs_counter 17
#define XENOPROF_last_op 17
#define MAX_OPROF_EVENTS 32
#define MAX_OPROF_DOMAINS 25
@@ -124,6 +128,16 @@ typedef struct xenoprof_passive {
} xenoprof_passive_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
struct xenoprof_ibs_counter {
uint64_t op_enabled;
uint64_t fetch_enabled;
uint64_t max_cnt_fetch;
uint64_t max_cnt_op;
uint64_t rand_en;
uint64_t dispatched_ops;
};
typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
#endif /* __XEN_PUBLIC_XENOPROF_H__ */
+1
View File
@@ -107,6 +107,7 @@ struct scheduler {
void (*sleep) (const struct scheduler *, struct vcpu *);
void (*wake) (const struct scheduler *, struct vcpu *);
void (*yield) (const struct scheduler *, struct vcpu *);
void (*context_saved) (const struct scheduler *, struct vcpu *);
struct task_slice (*do_schedule) (const struct scheduler *, s_time_t,
+9
View File
@@ -23,6 +23,8 @@
#include <xen/mm.h>
#include <xen/tasklet.h>
#include <public/mem_event.h>
#include <xen/cpumask.h>
#include <xen/nodemask.h>
#ifdef CONFIG_COMPAT
#include <compat/vcpu.h>
@@ -326,6 +328,11 @@ struct domain
/* Memory paging support */
struct mem_event_domain mem_event;
/* Currently computed from union of all vcpu cpu-affinity masks. */
nodemask_t node_affinity;
unsigned int last_alloc_node;
spinlock_t node_affinity_lock;
};
struct domain_setup_info
@@ -393,6 +400,8 @@ static inline void get_knownalive_domain(struct domain *d)
ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
}
void domain_update_node_affinity(struct domain *d);
struct domain *domain_create(
domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
/* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.