ia64/xen-unstable

changeset 15481:87b0b6a08dbd

[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@fujitsu-siemens.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Jul 09 09:22:58 2007 -0600 (2007-07-09)
parents ba98732b44c7
children 42586a0f4407
files xen/arch/ia64/vmx/mmio.c xen/arch/ia64/vmx/vmx_fault.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/hypercall.c xen/arch/ia64/xen/vcpu.c xen/include/asm-ia64/domain.h xen/include/public/arch-ia64.h
line diff
     1.1 --- a/xen/arch/ia64/vmx/mmio.c	Mon Jul 09 08:33:02 2007 -0600
     1.2 +++ b/xen/arch/ia64/vmx/mmio.c	Mon Jul 09 09:22:58 2007 -0600
     1.3 @@ -200,6 +200,21 @@ static inline void set_os_type(VCPU *v, 
     1.4      if (type > OS_BASE && type < OS_END) {
     1.5          v->domain->arch.vmx_platform.gos_type = type;
     1.6          gdprintk(XENLOG_INFO, "Guest OS : %s\n", guest_os_name[type - OS_BASE]);
     1.7 +
     1.8 +        if (GOS_WINDOWS(v)) {
     1.9 +            struct xen_ia64_opt_feature optf;
    1.10 +
    1.11 +	    /* Windows identity maps regions 4 & 5 */
    1.12 +            optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4;
    1.13 +            optf.on = XEN_IA64_OPTF_ON;
    1.14 +            optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_WB|_PAGE_AR_RW);
    1.15 +            optf.key = 0;
    1.16 +            domain_opt_feature(&optf);
    1.17 +
    1.18 +            optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5;
    1.19 +            optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_UC|_PAGE_AR_RW);
    1.20 +            domain_opt_feature(&optf);
    1.21 +        }
    1.22      }
    1.23  }
    1.24  
     2.1 --- a/xen/arch/ia64/vmx/vmx_fault.c	Mon Jul 09 08:33:02 2007 -0600
     2.2 +++ b/xen/arch/ia64/vmx/vmx_fault.c	Mon Jul 09 09:22:58 2007 -0600
     2.3 @@ -375,7 +375,8 @@ try_again:
     2.4          thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
     2.5  
     2.6      } else if (type == DSIDE_TLB) {
     2.7 -    
     2.8 +        struct opt_feature* optf = &(v->domain->arch.opt_feature);
     2.9 +
    2.10          if (misr.sp)
    2.11              return vmx_handle_lds(regs);
    2.12  
    2.13 @@ -383,35 +384,27 @@ try_again:
    2.14          itir = rr & (RR_RID_MASK | RR_PS_MASK);
    2.15  
    2.16          if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) {
    2.17 -            if (GOS_WINDOWS(v)) {
    2.18 -                /* windows use region 4 and 5 for identity mapping */
    2.19 -                if (REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL)
    2.20 -                    && (REGION_OFFSET(vadr) <= _PAGE_PPN_MASK)) {
    2.21 -
    2.22 -                    pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
    2.23 -                             (_PAGE_P | _PAGE_A | _PAGE_D |
    2.24 -                               _PAGE_MA_WB | _PAGE_AR_RW);
    2.25 -
    2.26 -                    if (thash_purge_and_insert(v, pteval, itir, vadr, type))
    2.27 -                        goto try_again;
    2.28 -
    2.29 -                    return IA64_NO_FAULT;
    2.30 -                }
    2.31 +            /* windows use region 4 and 5 for identity mapping */
    2.32 +            if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4 &&
    2.33 +                REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL) &&
    2.34 +                REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) {
    2.35  
    2.36 -                if (REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL)
    2.37 -                    && (REGION_OFFSET(vadr) <= _PAGE_PPN_MASK)) {
    2.38 -
    2.39 -                    pteval = PAGEALIGN(REGION_OFFSET(vadr),itir_ps(itir)) |
    2.40 -                             (_PAGE_P | _PAGE_A | _PAGE_D |
    2.41 -                              _PAGE_MA_UC | _PAGE_AR_RW);
    2.42 +                pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
    2.43 +                         optf->im_reg4.pgprot;
    2.44 +                if (thash_purge_and_insert(v, pteval, itir, vadr, type))
    2.45 +                    goto try_again;
    2.46 +                return IA64_NO_FAULT;
    2.47 +            }
    2.48 +            if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5 &&
    2.49 +                REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL) &&
    2.50 +                REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) {
    2.51  
    2.52 -                    if (thash_purge_and_insert(v, pteval, itir, vadr, type))
    2.53 -                        goto try_again;
    2.54 -
    2.55 -                    return IA64_NO_FAULT;
    2.56 -                }
    2.57 +                pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
    2.58 +                         optf->im_reg5.pgprot;
    2.59 +                if (thash_purge_and_insert(v, pteval, itir, vadr, type))
    2.60 +                    goto try_again;
    2.61 +                return IA64_NO_FAULT;
    2.62              }
    2.63 -
    2.64              if (vpsr.ic) {
    2.65                  vcpu_set_isr(v, misr.val);
    2.66                  alt_dtlb(v, vadr);
    2.67 @@ -436,7 +429,8 @@ try_again:
    2.68          }
    2.69  
    2.70          /* avoid recursively walking (short format) VHPT */
    2.71 -        if (!GOS_WINDOWS(v) &&
    2.72 +        if (!(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4) &&
    2.73 +            !(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5) &&
    2.74              (((vadr ^ vpta.val) << 3) >> (vpta.size + 3)) == 0) {
    2.75  
    2.76              if (vpsr.ic) {
     3.1 --- a/xen/arch/ia64/xen/domain.c	Mon Jul 09 08:33:02 2007 -0600
     3.2 +++ b/xen/arch/ia64/xen/domain.c	Mon Jul 09 09:22:58 2007 -0600
     3.3 @@ -1515,3 +1515,48 @@ static void __init parse_dom0_mem(char *
     3.4  	dom0_size = parse_size_and_unit(s, NULL);
     3.5  }
     3.6  custom_param("dom0_mem", parse_dom0_mem);
     3.7 +
     3.8 +/*
     3.9 + * Helper function for the optimization stuff handling the identity mapping
    3.10 + * feature.
    3.11 + */
    3.12 +static inline void
    3.13 +optf_set_identity_mapping(unsigned long* mask, struct identity_mapping* im,
    3.14 +			  struct xen_ia64_opt_feature* f)
    3.15 +{
    3.16 +	if (f->on) {
    3.17 +		*mask |= f->cmd;
    3.18 +		im->pgprot = f->pgprot;
    3.19 +		im->key = f->key;
    3.20 +	} else {
    3.21 +		*mask &= ~(f->cmd);
    3.22 +		im->pgprot = 0;
    3.23 +		im->key = 0;
    3.24 +	}
    3.25 +}
    3.26 +
    3.27 +/* Switch a optimization feature on/off. */
    3.28 +int
    3.29 +domain_opt_feature(struct xen_ia64_opt_feature* f)
    3.30 +{
    3.31 +	struct opt_feature* optf = &(current->domain->arch.opt_feature);
    3.32 +	long rc = 0;
    3.33 +
    3.34 +	switch (f->cmd) {
    3.35 +	case XEN_IA64_OPTF_IDENT_MAP_REG4:
    3.36 +		optf_set_identity_mapping(&optf->mask, &optf->im_reg4, f);
    3.37 +		break;
    3.38 +	case XEN_IA64_OPTF_IDENT_MAP_REG5:
    3.39 +		optf_set_identity_mapping(&optf->mask, &optf->im_reg5, f);
    3.40 +		break;
    3.41 +	case XEN_IA64_OPTF_IDENT_MAP_REG7:
    3.42 +		optf_set_identity_mapping(&optf->mask, &optf->im_reg7, f);
    3.43 +		break;
    3.44 +	default:
    3.45 +		printk("%s: unknown opt_feature: %ld\n", __func__, f->cmd);
    3.46 +		rc = -ENOSYS;
    3.47 +		break;
    3.48 +	}
    3.49 +	return rc;
    3.50 +}
    3.51 +
     4.1 --- a/xen/arch/ia64/xen/hypercall.c	Mon Jul 09 08:33:02 2007 -0600
     4.2 +++ b/xen/arch/ia64/xen/hypercall.c	Mon Jul 09 09:22:58 2007 -0600
     4.3 @@ -224,6 +224,16 @@ ia64_hypercall(struct pt_regs *regs)
     4.4  		regs->r10 = fpswa_ret.err1;
     4.5  		regs->r11 = fpswa_ret.err2;
     4.6  		break;
     4.7 +	case __HYPERVISOR_opt_feature: {
     4.8 +		XEN_GUEST_HANDLE(void) arg;
     4.9 +		struct xen_ia64_opt_feature optf;
    4.10 +		set_xen_guest_handle(arg, (void*)(vcpu_get_gr(v, 32)));
    4.11 +		if (copy_from_guest(&optf, arg, 1) == 0)
    4.12 +			regs->r8 = domain_opt_feature(&optf);
    4.13 +		else
    4.14 +			regs->r8 = -EFAULT;
    4.15 +		break;
    4.16 +	}
    4.17  	default:
    4.18  		printk("unknown ia64 fw hypercall %lx\n", regs->r2);
    4.19  		regs->r8 = do_ni_hypercall();
     5.1 --- a/xen/arch/ia64/xen/vcpu.c	Mon Jul 09 08:33:02 2007 -0600
     5.2 +++ b/xen/arch/ia64/xen/vcpu.c	Mon Jul 09 09:22:58 2007 -0600
     5.3 @@ -1709,11 +1709,13 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6
     5.4  	vcpu_thash(vcpu, address, iha);
     5.5  	if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
     5.6  		REGS *regs = vcpu_regs(vcpu);
     5.7 -		// NOTE: This is specific code for linux kernel
     5.8 -		// We assume region 7 is identity mapped
     5.9 -		if (region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) {
    5.10 +		struct opt_feature* optf = &(vcpu->domain->arch.opt_feature);
    5.11 +
    5.12 +		/* Optimization for identity mapped region 7 OS (linux) */
    5.13 +		if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG7 &&
    5.14 +		    region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) {
    5.15  			pte.val = address & _PAGE_PPN_MASK;
    5.16 -			pte.val = pte.val | pgprot_val(PAGE_KERNEL);
    5.17 +			pte.val = pte.val | optf->im_reg7.pgprot;
    5.18  			goto out;
    5.19  		}
    5.20  		return is_data ? IA64_ALT_DATA_TLB_VECTOR :
     6.1 --- a/xen/include/asm-ia64/domain.h	Mon Jul 09 08:33:02 2007 -0600
     6.2 +++ b/xen/include/asm-ia64/domain.h	Mon Jul 09 09:22:58 2007 -0600
     6.3 @@ -66,6 +66,44 @@ struct xen_sal_data {
     6.4      int efi_virt_mode;		/* phys : 0 , virt : 1 */
     6.5  };
     6.6  
     6.7 +/*
     6.8 + * Optimization features
     6.9 + * are used by the hypervisor to do some optimizations for guests.
    6.10 + * By default the optimizations are switched off and the guest has to activate
    6.11 + * the feature. On PV the guest must do this via the hypercall
    6.12 + * __HYPERVISOR_opt_feature, on HVM it's done within xen in set_os_type().
    6.13 + */
    6.14 +
    6.15 +/*
    6.16 + * Helper struct for the different identity mapping optimizations.
    6.17 + * The hypervisor does the insertion of address translations in the tlb
    6.18 + * for identity mapped areas without reflecting the page fault
    6.19 + * to the guest.
    6.20 + */
    6.21 +struct identity_mapping {
    6.22 +        unsigned long pgprot;	/* The page protection bit mask of the pte.*/
    6.23 +        unsigned long key;	/* A protection key. */
    6.24 +};
    6.25 +
    6.26 +/* Central structure for optimzation features used by the hypervisor.  */
    6.27 +struct opt_feature {
    6.28 +    unsigned long mask;			/* For every feature one bit. */
    6.29 +    struct identity_mapping im_reg4;	/* Region 4 identity mapping */
    6.30 +    struct identity_mapping im_reg5;	/* Region 5 identity mapping */
    6.31 +    struct identity_mapping im_reg7;	/* Region 7 identity mapping */
    6.32 +};
    6.33 +
    6.34 +/*
    6.35 + * The base XEN_IA64_OPTF_IDENT_MAP_REG7 is defined in public/arch-ia64.h.
    6.36 + * Identity mapping of region 4 addresses in HVM.
    6.37 + */
    6.38 +#define XEN_IA64_OPTF_IDENT_MAP_REG4	(XEN_IA64_OPTF_IDENT_MAP_REG7 + 1)
    6.39 +/* Identity mapping of region 5 addresses in HVM. */
    6.40 +#define XEN_IA64_OPTF_IDENT_MAP_REG5	(XEN_IA64_OPTF_IDENT_MAP_REG4 + 1)
    6.41 +
    6.42 +/* Set an optimization feature in the struct arch_domain. */
    6.43 +extern int domain_opt_feature(struct xen_ia64_opt_feature*);
    6.44 +
    6.45  struct arch_domain {
    6.46      struct mm_struct mm;
    6.47  
    6.48 @@ -129,6 +167,8 @@ struct arch_domain {
    6.49  
    6.50      struct last_vcpu last_vcpu[NR_CPUS];
    6.51  
    6.52 +    struct opt_feature opt_feature;
    6.53 +
    6.54  #ifdef CONFIG_XEN_IA64_TLB_TRACK
    6.55      struct tlb_track*   tlb_track;
    6.56  #endif
     7.1 --- a/xen/include/public/arch-ia64.h	Mon Jul 09 08:33:02 2007 -0600
     7.2 +++ b/xen/include/public/arch-ia64.h	Mon Jul 09 09:22:58 2007 -0600
     7.3 @@ -558,6 +558,41 @@ struct xen_ia64_boot_param {
     7.4  #define XENCOMM_INLINE_ADDR(addr) \
     7.5    ((unsigned long)(addr) & ~XENCOMM_INLINE_MASK)
     7.6  
     7.7 +#ifndef __ASSEMBLY__
     7.8 +
     7.9 +/*
    7.10 + * Optimization features.
    7.11 + * The hypervisor may do some special optimizations for guests. This hypercall
    7.12 + * can be used to switch on/of these special optimizations.
    7.13 + */
    7.14 +#define __HYPERVISOR_opt_feature	0x700UL
    7.15 +
    7.16 +#define XEN_IA64_OPTF_OFF	0x0
    7.17 +#define XEN_IA64_OPTF_ON	0x1
    7.18 +
    7.19 +/*
    7.20 + * If this feature is switched on, the hypervisor inserts the
    7.21 + * tlb entries without calling the guests traphandler.
    7.22 + * This is useful in guests using region 7 for identity mapping
    7.23 + * like the linux kernel does.
    7.24 + */
    7.25 +#define XEN_IA64_OPTF_IDENT_MAP_REG7	0x1UL
    7.26 +
    7.27 +struct xen_ia64_opt_feature {
    7.28 +	unsigned long cmd;		/* Which feature */
    7.29 +	unsigned char on;		/* Switch feature on/off */
    7.30 +	union {
    7.31 +		struct {
    7.32 +				/* The page protection bit mask of the pte.
    7.33 +			 	 * This will be or'ed with the pte. */
    7.34 +			unsigned long pgprot;
    7.35 +			unsigned long key;	/* A protection key for itir. */
    7.36 +		};
    7.37 +	};
    7.38 +};
    7.39 +
    7.40 +#endif /* __ASSEMBLY__ */
    7.41 +
    7.42  /* xen perfmon */
    7.43  #ifdef XEN
    7.44  #ifndef __ASSEMBLY__