ia64/xen-unstable

changeset 15664:57f519c41534

[IA64] Switch on PKR

First implementation of handling protection keys in domU's. Currently
only 15 registers are usable by domU's. pkr[15] is reserved for the
hypervisor. The hypervisor doesn't take care of entries with the same key.

Signed-off-by: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Jul 30 16:51:52 2007 -0600 (2007-07-30)
parents 255abff9d1f7
children d69a57b29e3f
files xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/vcpu.c xen/include/asm-ia64/domain.h xen/include/asm-ia64/vcpu.h xen/include/asm-ia64/xenkregs.h
line diff
     1.1 --- a/xen/arch/ia64/xen/domain.c	Mon Jul 30 16:38:47 2007 -0600
     1.2 +++ b/xen/arch/ia64/xen/domain.c	Mon Jul 30 16:51:52 2007 -0600
     1.3 @@ -262,6 +262,8 @@ void context_switch(struct vcpu *prev, s
     1.4              load_region_regs(current);
     1.5              ia64_set_pta(vcpu_pta(current));
     1.6              vcpu_load_kernel_regs(current);
     1.7 +            if (vcpu_pkr_in_use(current))
     1.8 +                vcpu_pkr_load_regs(current);
     1.9              vcpu_set_next_timer(current);
    1.10              if (vcpu_timer_expired(current))
    1.11                  vcpu_pend_timer(current);
     2.1 --- a/xen/arch/ia64/xen/vcpu.c	Mon Jul 30 16:38:47 2007 -0600
     2.2 +++ b/xen/arch/ia64/xen/vcpu.c	Mon Jul 30 16:51:52 2007 -0600
     2.3 @@ -242,6 +242,42 @@ IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 r
     2.4  }
     2.5  
     2.6  /**************************************************************************
     2.7 + VCPU protection key emulating for PV
     2.8 + This first implementation reserves 1 pkr for the hypervisor key.
     2.9 + On setting psr.pk the hypervisor key is loaded in pkr[15], therewith the
    2.10 + hypervisor may run with psr.pk==1. The key for the hypervisor is 0.
    2.11 + Furthermore the VCPU is flagged to use the protection keys.
    2.12 + Currently the domU has to take care of the used keys, because on setting
    2.13 + a pkr there is no check against other pkr's whether this key is already
    2.14 + used.
    2.15 +**************************************************************************/
    2.16 +
    2.17 +/* The function loads the protection key registers from the struct arch_vcpu
    2.18 + * into the processor pkr's! Called in context_switch().
    2.19 + * TODO: take care of the order of writing pkr's!
    2.20 + */
    2.21 +void vcpu_pkr_load_regs(VCPU * vcpu)
    2.22 +{
    2.23 +	int i;
    2.24 +
    2.25 +	for (i = 0; i <= XEN_IA64_NPKRS; i++)
    2.26 +		ia64_set_pkr(i, PSCBX(vcpu, pkrs[i]));
    2.27 +}
    2.28 +
    2.29 +/* The function activates the pkr handling. */
    2.30 +static void vcpu_pkr_set_psr_handling(VCPU * vcpu)
    2.31 +{
    2.32 +	if (PSCBX(vcpu, pkr_flags) & XEN_IA64_PKR_IN_USE)
    2.33 +		return;
    2.34 +
    2.35 +	vcpu_pkr_use_set(vcpu);
    2.36 +	PSCBX(vcpu, pkrs[XEN_IA64_NPKRS]) = XEN_IA64_PKR_VAL;
    2.37 +
    2.38 +	/* Write the special key for the hypervisor into pkr[15]. */
    2.39 +	ia64_set_pkr(XEN_IA64_NPKRS, XEN_IA64_PKR_VAL);
    2.40 +}
    2.41 +
    2.42 +/**************************************************************************
    2.43   VCPU processor status register access routines
    2.44  **************************************************************************/
    2.45  
    2.46 @@ -284,7 +320,7 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu,
    2.47  	// just handle psr.up and psr.pp for now
    2.48  	if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
    2.49  		      IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
    2.50 -		      IA64_PSR_DFL | IA64_PSR_DFH))
    2.51 +		      IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_PK))
    2.52  		return IA64_ILLOP_FAULT;
    2.53  	if (imm.dfh) {
    2.54  		ipsr->dfh = PSCB(vcpu, hpsr_dfh);
    2.55 @@ -309,6 +345,10 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu,
    2.56  		ipsr->be = 0;
    2.57  	if (imm.dt)
    2.58  		vcpu_set_metaphysical_mode(vcpu, TRUE);
    2.59 +	if (imm.pk) {
    2.60 +		ipsr->pk = 0;
    2.61 +		vcpu_pkr_use_unset(vcpu);
    2.62 +	}
    2.63  	__asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
    2.64  	return IA64_NO_FAULT;
    2.65  }
    2.66 @@ -340,7 +380,8 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u
    2.67  	// just handle psr.sp,pp and psr.i,ic (and user mask) for now
    2.68  	mask =
    2.69  	    IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
    2.70 -	    IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE;
    2.71 +	    IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE |
    2.72 +	    IA64_PSR_PK;
    2.73  	if (imm24 & ~mask)
    2.74  		return IA64_ILLOP_FAULT;
    2.75  	if (imm.dfh) {
    2.76 @@ -388,6 +429,10 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u
    2.77  		ipsr->be = 1;
    2.78  	if (imm.dt)
    2.79  		vcpu_set_metaphysical_mode(vcpu, FALSE);
    2.80 +	if (imm.pk) {
    2.81 +		vcpu_pkr_set_psr_handling(vcpu);
    2.82 +		ipsr->pk = 1;
    2.83 +	}
    2.84  	__asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
    2.85  	if (enabling_interrupts &&
    2.86  	    vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
    2.87 @@ -448,6 +493,11 @@ IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u6
    2.88  		vcpu_set_metaphysical_mode(vcpu, TRUE);
    2.89  	if (newpsr.be)
    2.90  		ipsr->be = 1;
    2.91 +	if (newpsr.pk) {
    2.92 +		vcpu_pkr_set_psr_handling(vcpu);
    2.93 +		ipsr->pk = 1;
    2.94 +	} else
    2.95 +		vcpu_pkr_use_unset(vcpu);
    2.96  	if (enabling_interrupts &&
    2.97  	    vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
    2.98  		PSCB(vcpu, pending_interruption) = 1;
    2.99 @@ -504,6 +554,11 @@ IA64FAULT vcpu_set_psr(VCPU * vcpu, u64 
   2.100  		else
   2.101  			vcpu_bsw0(vcpu);
   2.102  	}
   2.103 +	if (vpsr.pk) {
   2.104 +		vcpu_pkr_set_psr_handling(vcpu);
   2.105 +		newpsr.pk = 1;
   2.106 +	} else
   2.107 +		vcpu_pkr_use_unset(vcpu);
   2.108  
   2.109  	regs->cr_ipsr = newpsr.val;
   2.110  
   2.111 @@ -2058,14 +2113,31 @@ IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 r
   2.112  
   2.113  IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
   2.114  {
   2.115 -	printk("vcpu_get_pkr: called, not implemented yet\n");
   2.116 -	return IA64_ILLOP_FAULT;
   2.117 +	if (reg > XEN_IA64_NPKRS)
   2.118 +		return IA64_RSVDREG_FAULT;	/* register index to large */
   2.119 +
   2.120 +	*pval = (u64) PSCBX(vcpu, pkrs[reg]);
   2.121 +	return IA64_NO_FAULT;
   2.122  }
   2.123  
   2.124  IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
   2.125  {
   2.126 -	printk("vcpu_set_pkr: called, not implemented yet\n");
   2.127 -	return IA64_ILLOP_FAULT;
   2.128 +	ia64_pkr_t pkr_new;
   2.129 +
   2.130 +	if (reg >= XEN_IA64_NPKRS)
   2.131 +		return IA64_RSVDREG_FAULT;	/* index to large */
   2.132 +
   2.133 +	pkr_new.val = val;
   2.134 +	if (pkr_new.reserved1)
   2.135 +		return IA64_RSVDREG_FAULT;	/* reserved field */
   2.136 +
   2.137 +	if (pkr_new.reserved2)
   2.138 +		return IA64_RSVDREG_FAULT;	/* reserved field */
   2.139 +
   2.140 +	PSCBX(vcpu, pkrs[reg]) = pkr_new.val;
   2.141 +	ia64_set_pkr(reg, pkr_new.val);
   2.142 +
   2.143 +	return IA64_NO_FAULT;
   2.144  }
   2.145  
   2.146  /**************************************************************************
     3.1 --- a/xen/include/asm-ia64/domain.h	Mon Jul 30 16:38:47 2007 -0600
     3.2 +++ b/xen/include/asm-ia64/domain.h	Mon Jul 30 16:51:52 2007 -0600
     3.3 @@ -239,6 +239,13 @@ struct arch_vcpu {
     3.4      struct timer hlt_timer;
     3.5      struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
     3.6  
     3.7 +    /* This vector hosts the protection keys for pkr emulation of PV domains.
     3.8 +     * Currently only 15 registers are usable by domU's. pkr[15] is
     3.9 +     * reserved for the hypervisor. */
    3.10 +    unsigned long pkrs[XEN_IA64_NPKRS+1];	/* protection key registers */
    3.11 +#define XEN_IA64_PKR_IN_USE	0x1		/* If psr.pk = 1 was set. */
    3.12 +    unsigned char pkr_flags;
    3.13 +
    3.14  #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    3.15      PTA                 pta;
    3.16      unsigned long       vhpt_maddr;
     4.1 --- a/xen/include/asm-ia64/vcpu.h	Mon Jul 30 16:38:47 2007 -0600
     4.2 +++ b/xen/include/asm-ia64/vcpu.h	Mon Jul 30 16:51:52 2007 -0600
     4.3 @@ -125,6 +125,19 @@ extern IA64FAULT vcpu_set_rr(VCPU * vcpu
     4.4  extern IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval);
     4.5  extern IA64FAULT vcpu_get_rr_ve(VCPU * vcpu, u64 vadr);
     4.6  /* protection key registers */
     4.7 +extern void vcpu_pkr_load_regs(VCPU * vcpu);
     4.8 +static inline int vcpu_pkr_in_use(VCPU * vcpu)
     4.9 +{
    4.10 +	return (PSCBX(vcpu, pkr_flags) & XEN_IA64_PKR_IN_USE);
    4.11 +}
    4.12 +static inline void vcpu_pkr_use_set(VCPU * vcpu)
    4.13 +{
    4.14 +	PSCBX(vcpu, pkr_flags) |= XEN_IA64_PKR_IN_USE;
    4.15 +}
    4.16 +static inline void vcpu_pkr_use_unset(VCPU * vcpu)
    4.17 +{
    4.18 +	PSCBX(vcpu, pkr_flags) &= ~XEN_IA64_PKR_IN_USE;
    4.19 +}
    4.20  extern IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval);
    4.21  extern IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val);
    4.22  extern IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key);
     5.1 --- a/xen/include/asm-ia64/xenkregs.h	Mon Jul 30 16:38:47 2007 -0600
     5.2 +++ b/xen/include/asm-ia64/xenkregs.h	Mon Jul 30 16:51:52 2007 -0600
     5.3 @@ -63,4 +63,7 @@
     5.4  
     5.5  #define	XEN_IA64_NPKRS		15	/* Number of pkr's in PV */
     5.6  
     5.7 +  	/* A pkr val for the hypervisor: key = 0, valid = 1. */
     5.8 +#define XEN_IA64_PKR_VAL	((0 << IA64_PKR_KEY) | IA64_PKR_VALID)
     5.9 +
    5.10  #endif /* _ASM_IA64_XENKREGS_H */