[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] Switch on PKR



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1185835912 21600
# Node ID 57f519c41534de7448f8029df96917ffd71f6334
# Parent  255abff9d1f75f1dd1502e5764c736835232712f
[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@xxxxxxxxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/domain.c      |    2 
 xen/arch/ia64/xen/vcpu.c        |   84 +++++++++++++++++++++++++++++++++++++---
 xen/include/asm-ia64/domain.h   |    7 +++
 xen/include/asm-ia64/vcpu.h     |   13 ++++++
 xen/include/asm-ia64/xenkregs.h |    3 +
 5 files changed, 103 insertions(+), 6 deletions(-)

diff -r 255abff9d1f7 -r 57f519c41534 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Mon Jul 30 16:38:47 2007 -0600
+++ b/xen/arch/ia64/xen/domain.c        Mon Jul 30 16:51:52 2007 -0600
@@ -262,6 +262,8 @@ void context_switch(struct vcpu *prev, s
             load_region_regs(current);
             ia64_set_pta(vcpu_pta(current));
             vcpu_load_kernel_regs(current);
+            if (vcpu_pkr_in_use(current))
+                vcpu_pkr_load_regs(current);
             vcpu_set_next_timer(current);
             if (vcpu_timer_expired(current))
                 vcpu_pend_timer(current);
diff -r 255abff9d1f7 -r 57f519c41534 xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c  Mon Jul 30 16:38:47 2007 -0600
+++ b/xen/arch/ia64/xen/vcpu.c  Mon Jul 30 16:51:52 2007 -0600
@@ -242,6 +242,42 @@ IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 r
 }
 
 /**************************************************************************
+ VCPU protection key emulating for PV
+ This first implementation reserves 1 pkr for the hypervisor key.
+ On setting psr.pk the hypervisor key is loaded in pkr[15], therewith the
+ hypervisor may run with psr.pk==1. The key for the hypervisor is 0.
+ Furthermore the VCPU is flagged to use the protection keys.
+ Currently the domU has to take care of the used keys, because on setting
+ a pkr there is no check against other pkr's whether this key is already
+ used.
+**************************************************************************/
+
+/* The function loads the protection key registers from the struct arch_vcpu
+ * into the processor pkr's! Called in context_switch().
+ * TODO: take care of the order of writing pkr's!
+ */
+void vcpu_pkr_load_regs(VCPU * vcpu)
+{
+       int i;
+
+       for (i = 0; i <= XEN_IA64_NPKRS; i++)
+               ia64_set_pkr(i, PSCBX(vcpu, pkrs[i]));
+}
+
+/* The function activates the pkr handling. */
+static void vcpu_pkr_set_psr_handling(VCPU * vcpu)
+{
+       if (PSCBX(vcpu, pkr_flags) & XEN_IA64_PKR_IN_USE)
+               return;
+
+       vcpu_pkr_use_set(vcpu);
+       PSCBX(vcpu, pkrs[XEN_IA64_NPKRS]) = XEN_IA64_PKR_VAL;
+
+       /* Write the special key for the hypervisor into pkr[15]. */
+       ia64_set_pkr(XEN_IA64_NPKRS, XEN_IA64_PKR_VAL);
+}
+
+/**************************************************************************
  VCPU processor status register access routines
 **************************************************************************/
 
@@ -284,7 +320,7 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu,
        // just handle psr.up and psr.pp for now
        if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
                      IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
-                     IA64_PSR_DFL | IA64_PSR_DFH))
+                     IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_PK))
                return IA64_ILLOP_FAULT;
        if (imm.dfh) {
                ipsr->dfh = PSCB(vcpu, hpsr_dfh);
@@ -309,6 +345,10 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu,
                ipsr->be = 0;
        if (imm.dt)
                vcpu_set_metaphysical_mode(vcpu, TRUE);
+       if (imm.pk) {
+               ipsr->pk = 0;
+               vcpu_pkr_use_unset(vcpu);
+       }
        __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
        return IA64_NO_FAULT;
 }
@@ -340,7 +380,8 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u
        // just handle psr.sp,pp and psr.i,ic (and user mask) for now
        mask =
            IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
-           IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE;
+           IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE |
+           IA64_PSR_PK;
        if (imm24 & ~mask)
                return IA64_ILLOP_FAULT;
        if (imm.dfh) {
@@ -388,6 +429,10 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u
                ipsr->be = 1;
        if (imm.dt)
                vcpu_set_metaphysical_mode(vcpu, FALSE);
+       if (imm.pk) {
+               vcpu_pkr_set_psr_handling(vcpu);
+               ipsr->pk = 1;
+       }
        __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
        if (enabling_interrupts &&
            vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
@@ -448,6 +493,11 @@ IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u6
                vcpu_set_metaphysical_mode(vcpu, TRUE);
        if (newpsr.be)
                ipsr->be = 1;
+       if (newpsr.pk) {
+               vcpu_pkr_set_psr_handling(vcpu);
+               ipsr->pk = 1;
+       } else
+               vcpu_pkr_use_unset(vcpu);
        if (enabling_interrupts &&
            vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
                PSCB(vcpu, pending_interruption) = 1;
@@ -504,6 +554,11 @@ IA64FAULT vcpu_set_psr(VCPU * vcpu, u64 
                else
                        vcpu_bsw0(vcpu);
        }
+       if (vpsr.pk) {
+               vcpu_pkr_set_psr_handling(vcpu);
+               newpsr.pk = 1;
+       } else
+               vcpu_pkr_use_unset(vcpu);
 
        regs->cr_ipsr = newpsr.val;
 
@@ -2058,14 +2113,31 @@ IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 r
 
 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
 {
-       printk("vcpu_get_pkr: called, not implemented yet\n");
-       return IA64_ILLOP_FAULT;
+       if (reg > XEN_IA64_NPKRS)
+               return IA64_RSVDREG_FAULT;      /* register index to large */
+
+       *pval = (u64) PSCBX(vcpu, pkrs[reg]);
+       return IA64_NO_FAULT;
 }
 
 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
 {
-       printk("vcpu_set_pkr: called, not implemented yet\n");
-       return IA64_ILLOP_FAULT;
+       ia64_pkr_t pkr_new;
+
+       if (reg >= XEN_IA64_NPKRS)
+               return IA64_RSVDREG_FAULT;      /* index to large */
+
+       pkr_new.val = val;
+       if (pkr_new.reserved1)
+               return IA64_RSVDREG_FAULT;      /* reserved field */
+
+       if (pkr_new.reserved2)
+               return IA64_RSVDREG_FAULT;      /* reserved field */
+
+       PSCBX(vcpu, pkrs[reg]) = pkr_new.val;
+       ia64_set_pkr(reg, pkr_new.val);
+
+       return IA64_NO_FAULT;
 }
 
 /**************************************************************************
diff -r 255abff9d1f7 -r 57f519c41534 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Mon Jul 30 16:38:47 2007 -0600
+++ b/xen/include/asm-ia64/domain.h     Mon Jul 30 16:51:52 2007 -0600
@@ -239,6 +239,13 @@ struct arch_vcpu {
     struct timer hlt_timer;
     struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
 
+    /* This vector hosts the protection keys for pkr emulation of PV domains.
+     * Currently only 15 registers are usable by domU's. pkr[15] is
+     * reserved for the hypervisor. */
+    unsigned long pkrs[XEN_IA64_NPKRS+1];      /* protection key registers */
+#define XEN_IA64_PKR_IN_USE    0x1             /* If psr.pk = 1 was set. */
+    unsigned char pkr_flags;
+
 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
     PTA                 pta;
     unsigned long       vhpt_maddr;
diff -r 255abff9d1f7 -r 57f519c41534 xen/include/asm-ia64/vcpu.h
--- a/xen/include/asm-ia64/vcpu.h       Mon Jul 30 16:38:47 2007 -0600
+++ b/xen/include/asm-ia64/vcpu.h       Mon Jul 30 16:51:52 2007 -0600
@@ -125,6 +125,19 @@ extern IA64FAULT vcpu_get_rr(VCPU * vcpu
 extern IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval);
 extern IA64FAULT vcpu_get_rr_ve(VCPU * vcpu, u64 vadr);
 /* protection key registers */
+extern void vcpu_pkr_load_regs(VCPU * vcpu);
+static inline int vcpu_pkr_in_use(VCPU * vcpu)
+{
+       return (PSCBX(vcpu, pkr_flags) & XEN_IA64_PKR_IN_USE);
+}
+static inline void vcpu_pkr_use_set(VCPU * vcpu)
+{
+       PSCBX(vcpu, pkr_flags) |= XEN_IA64_PKR_IN_USE;
+}
+static inline void vcpu_pkr_use_unset(VCPU * vcpu)
+{
+       PSCBX(vcpu, pkr_flags) &= ~XEN_IA64_PKR_IN_USE;
+}
 extern IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval);
 extern IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val);
 extern IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key);
diff -r 255abff9d1f7 -r 57f519c41534 xen/include/asm-ia64/xenkregs.h
--- a/xen/include/asm-ia64/xenkregs.h   Mon Jul 30 16:38:47 2007 -0600
+++ b/xen/include/asm-ia64/xenkregs.h   Mon Jul 30 16:51:52 2007 -0600
@@ -63,4 +63,7 @@
 
 #define        XEN_IA64_NPKRS          15      /* Number of pkr's in PV */
 
+       /* A pkr val for the hypervisor: key = 0, valid = 1. */
+#define XEN_IA64_PKR_VAL       ((0 << IA64_PKR_KEY) | IA64_PKR_VALID)
+
 #endif /* _ASM_IA64_XENKREGS_H */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.