# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1183994578 21600
# Node ID 87b0b6a08dbdf5882c6223b0b6b7b189a15b0482
# Parent ba98732b44c797fb452f842a1174104f16ae94da
[IA64] Support special guest optimizations in the hypervisor
For PV add a new hypercall __HYPERVISOR_opt_feature, which lets dom0/domU
switch on/off special optimization features in the hypervisor.
For HVM this is done in set_os_type().
Signed-off-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx>
---
xen/arch/ia64/vmx/mmio.c | 15 ++++++++++
xen/arch/ia64/vmx/vmx_fault.c | 56 ++++++++++++++++++-----------------------
xen/arch/ia64/xen/domain.c | 45 ++++++++++++++++++++++++++++++++
xen/arch/ia64/xen/hypercall.c | 10 +++++++
xen/arch/ia64/xen/vcpu.c | 10 ++++---
xen/include/asm-ia64/domain.h | 40 +++++++++++++++++++++++++++++
xen/include/public/arch-ia64.h | 35 +++++++++++++++++++++++++
7 files changed, 176 insertions(+), 35 deletions(-)
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/arch/ia64/vmx/mmio.c Mon Jul 09 09:22:58 2007 -0600
@@ -200,6 +200,21 @@ static inline void set_os_type(VCPU *v,
if (type > OS_BASE && type < OS_END) {
v->domain->arch.vmx_platform.gos_type = type;
gdprintk(XENLOG_INFO, "Guest OS : %s\n", guest_os_name[type -
OS_BASE]);
+
+ if (GOS_WINDOWS(v)) {
+ struct xen_ia64_opt_feature optf;
+
+ /* Windows identity maps regions 4 & 5 */
+ optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4;
+ optf.on = XEN_IA64_OPTF_ON;
+ optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_WB|_PAGE_AR_RW);
+ optf.key = 0;
+ domain_opt_feature(&optf);
+
+ optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5;
+ optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_UC|_PAGE_AR_RW);
+ domain_opt_feature(&optf);
+ }
}
}
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/arch/ia64/vmx/vmx_fault.c
--- a/xen/arch/ia64/vmx/vmx_fault.c Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/arch/ia64/vmx/vmx_fault.c Mon Jul 09 09:22:58 2007 -0600
@@ -375,7 +375,8 @@ try_again:
thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
} else if (type == DSIDE_TLB) {
-
+ struct opt_feature* optf = &(v->domain->arch.opt_feature);
+
if (misr.sp)
return vmx_handle_lds(regs);
@@ -383,35 +384,27 @@ try_again:
itir = rr & (RR_RID_MASK | RR_PS_MASK);
if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) {
- if (GOS_WINDOWS(v)) {
- /* windows use region 4 and 5 for identity mapping */
- if (REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL)
- && (REGION_OFFSET(vadr) <= _PAGE_PPN_MASK)) {
-
- pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
- (_PAGE_P | _PAGE_A | _PAGE_D |
- _PAGE_MA_WB | _PAGE_AR_RW);
-
- if (thash_purge_and_insert(v, pteval, itir, vadr, type))
- goto try_again;
-
- return IA64_NO_FAULT;
- }
-
- if (REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL)
- && (REGION_OFFSET(vadr) <= _PAGE_PPN_MASK)) {
-
- pteval = PAGEALIGN(REGION_OFFSET(vadr),itir_ps(itir)) |
- (_PAGE_P | _PAGE_A | _PAGE_D |
- _PAGE_MA_UC | _PAGE_AR_RW);
-
- if (thash_purge_and_insert(v, pteval, itir, vadr, type))
- goto try_again;
-
- return IA64_NO_FAULT;
- }
- }
-
+ /* windows use region 4 and 5 for identity mapping */
+ if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4 &&
+ REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL) &&
+ REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) {
+
+ pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
+ optf->im_reg4.pgprot;
+ if (thash_purge_and_insert(v, pteval, itir, vadr, type))
+ goto try_again;
+ return IA64_NO_FAULT;
+ }
+ if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5 &&
+ REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL) &&
+ REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) {
+
+ pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
+ optf->im_reg5.pgprot;
+ if (thash_purge_and_insert(v, pteval, itir, vadr, type))
+ goto try_again;
+ return IA64_NO_FAULT;
+ }
if (vpsr.ic) {
vcpu_set_isr(v, misr.val);
alt_dtlb(v, vadr);
@@ -436,7 +429,8 @@ try_again:
}
/* avoid recursively walking (short format) VHPT */
- if (!GOS_WINDOWS(v) &&
+ if (!(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4) &&
+ !(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5) &&
(((vadr ^ vpta.val) << 3) >> (vpta.size + 3)) == 0) {
if (vpsr.ic) {
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/arch/ia64/xen/domain.c Mon Jul 09 09:22:58 2007 -0600
@@ -1515,3 +1515,48 @@ static void __init parse_dom0_mem(char *
dom0_size = parse_size_and_unit(s, NULL);
}
custom_param("dom0_mem", parse_dom0_mem);
+
+/*
+ * Helper function for the optimization stuff handling the identity mapping
+ * feature.
+ */
+static inline void
+optf_set_identity_mapping(unsigned long* mask, struct identity_mapping* im,
+ struct xen_ia64_opt_feature* f)
+{
+ if (f->on) {
+ *mask |= f->cmd;
+ im->pgprot = f->pgprot;
+ im->key = f->key;
+ } else {
+ *mask &= ~(f->cmd);
+ im->pgprot = 0;
+ im->key = 0;
+ }
+}
+
+/* Switch a optimization feature on/off. */
+int
+domain_opt_feature(struct xen_ia64_opt_feature* f)
+{
+ struct opt_feature* optf = &(current->domain->arch.opt_feature);
+ long rc = 0;
+
+ switch (f->cmd) {
+ case XEN_IA64_OPTF_IDENT_MAP_REG4:
+ optf_set_identity_mapping(&optf->mask, &optf->im_reg4, f);
+ break;
+ case XEN_IA64_OPTF_IDENT_MAP_REG5:
+ optf_set_identity_mapping(&optf->mask, &optf->im_reg5, f);
+ break;
+ case XEN_IA64_OPTF_IDENT_MAP_REG7:
+ optf_set_identity_mapping(&optf->mask, &optf->im_reg7, f);
+ break;
+ default:
+ printk("%s: unknown opt_feature: %ld\n", __func__, f->cmd);
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/arch/ia64/xen/hypercall.c Mon Jul 09 09:22:58 2007 -0600
@@ -224,6 +224,16 @@ ia64_hypercall(struct pt_regs *regs)
regs->r10 = fpswa_ret.err1;
regs->r11 = fpswa_ret.err2;
break;
+ case __HYPERVISOR_opt_feature: {
+ XEN_GUEST_HANDLE(void) arg;
+ struct xen_ia64_opt_feature optf;
+ set_xen_guest_handle(arg, (void*)(vcpu_get_gr(v, 32)));
+ if (copy_from_guest(&optf, arg, 1) == 0)
+ regs->r8 = domain_opt_feature(&optf);
+ else
+ regs->r8 = -EFAULT;
+ break;
+ }
default:
printk("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/arch/ia64/xen/vcpu.c Mon Jul 09 09:22:58 2007 -0600
@@ -1709,11 +1709,13 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6
vcpu_thash(vcpu, address, iha);
if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
REGS *regs = vcpu_regs(vcpu);
- // NOTE: This is specific code for linux kernel
- // We assume region 7 is identity mapped
- if (region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) {
+ struct opt_feature* optf = &(vcpu->domain->arch.opt_feature);
+
+ /* Optimization for identity mapped region 7 OS (linux) */
+ if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG7 &&
+ region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) {
pte.val = address & _PAGE_PPN_MASK;
- pte.val = pte.val | pgprot_val(PAGE_KERNEL);
+ pte.val = pte.val | optf->im_reg7.pgprot;
goto out;
}
return is_data ? IA64_ALT_DATA_TLB_VECTOR :
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/include/asm-ia64/domain.h Mon Jul 09 09:22:58 2007 -0600
@@ -65,6 +65,44 @@ struct xen_sal_data {
/* There are these for EFI_SET_VIRTUAL_ADDRESS_MAP emulation. */
int efi_virt_mode; /* phys : 0 , virt : 1 */
};
+
+/*
+ * Optimization features
+ * are used by the hypervisor to do some optimizations for guests.
+ * By default the optimizations are switched off and the guest has to activate
+ * the feature. On PV the guest must do this via the hypercall
+ * __HYPERVISOR_opt_feature, on HVM it's done within xen in set_os_type().
+ */
+
+/*
+ * Helper struct for the different identity mapping optimizations.
+ * The hypervisor does the insertion of address translations in the tlb
+ * for identity mapped areas without reflecting the page fault
+ * to the guest.
+ */
+struct identity_mapping {
+ unsigned long pgprot; /* The page protection bit mask of the pte.*/
+ unsigned long key; /* A protection key. */
+};
+
+/* Central structure for optimzation features used by the hypervisor. */
+struct opt_feature {
+ unsigned long mask; /* For every feature one bit. */
+ struct identity_mapping im_reg4; /* Region 4 identity mapping */
+ struct identity_mapping im_reg5; /* Region 5 identity mapping */
+ struct identity_mapping im_reg7; /* Region 7 identity mapping */
+};
+
+/*
+ * The base XEN_IA64_OPTF_IDENT_MAP_REG7 is defined in public/arch-ia64.h.
+ * Identity mapping of region 4 addresses in HVM.
+ */
+#define XEN_IA64_OPTF_IDENT_MAP_REG4 (XEN_IA64_OPTF_IDENT_MAP_REG7 + 1)
+/* Identity mapping of region 5 addresses in HVM. */
+#define XEN_IA64_OPTF_IDENT_MAP_REG5 (XEN_IA64_OPTF_IDENT_MAP_REG4 + 1)
+
+/* Set an optimization feature in the struct arch_domain. */
+extern int domain_opt_feature(struct xen_ia64_opt_feature*);
struct arch_domain {
struct mm_struct mm;
@@ -129,6 +167,8 @@ struct arch_domain {
struct last_vcpu last_vcpu[NR_CPUS];
+ struct opt_feature opt_feature;
+
#ifdef CONFIG_XEN_IA64_TLB_TRACK
struct tlb_track* tlb_track;
#endif
diff -r ba98732b44c7 -r 87b0b6a08dbd xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Mon Jul 09 08:33:02 2007 -0600
+++ b/xen/include/public/arch-ia64.h Mon Jul 09 09:22:58 2007 -0600
@@ -558,6 +558,41 @@ struct xen_ia64_boot_param {
#define XENCOMM_INLINE_ADDR(addr) \
((unsigned long)(addr) & ~XENCOMM_INLINE_MASK)
+#ifndef __ASSEMBLY__
+
+/*
+ * Optimization features.
+ * The hypervisor may do some special optimizations for guests. This hypercall
+ * can be used to switch on/of these special optimizations.
+ */
+#define __HYPERVISOR_opt_feature 0x700UL
+
+#define XEN_IA64_OPTF_OFF 0x0
+#define XEN_IA64_OPTF_ON 0x1
+
+/*
+ * If this feature is switched on, the hypervisor inserts the
+ * tlb entries without calling the guests traphandler.
+ * This is useful in guests using region 7 for identity mapping
+ * like the linux kernel does.
+ */
+#define XEN_IA64_OPTF_IDENT_MAP_REG7 0x1UL
+
+struct xen_ia64_opt_feature {
+ unsigned long cmd; /* Which feature */
+ unsigned char on; /* Switch feature on/off */
+ union {
+ struct {
+ /* The page protection bit mask of the pte.
+ * This will be or'ed with the pte. */
+ unsigned long pgprot;
+ unsigned long key; /* A protection key for itir. */
+ };
+ };
+};
+
+#endif /* __ASSEMBLY__ */
+
/* xen perfmon */
#ifdef XEN
#ifndef __ASSEMBLY__
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|