#define LOAD_HANDLER(reg, label)                                       \
        addi    reg,reg,(label)-_stext; /* virt addr of handler ... */
 
-#define EXCEPTION_PROLOG_1(area)                               \
-       mfspr   r13,SPRN_SPRG_PACA;     /* get paca address into r13 */ \
+#define EXCEPTION_PROLOG_1(area)                                       \
+       GET_PACA(r13);                                                  \
        std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
        std     r10,area+EX_R10(r13);                                   \
        std     r11,area+EX_R11(r13);                                   \
        HMT_MEDIUM;                                                     \
        DO_KVM  n;                                                      \
        mtspr   SPRN_SPRG_SCRATCH0,r13; /* save r13 */                  \
-       mfspr   r13,SPRN_SPRG_PACA;     /* get paca address into r13 */ \
+       GET_PACA(r13);                                                  \
        std     r9,PACA_EXGEN+EX_R9(r13);       /* save r9, r10 */      \
        std     r10,PACA_EXGEN+EX_R10(r13);                             \
        lbz     r10,PACASOFTIRQEN(r13);                                 \
 
  * SPRG usage:
  *
  * All 64-bit:
- *     - SPRG1 stores PACA pointer
+ *     - SPRG1 stores PACA pointer except 64-bit server in
+ *        HV mode in which case it is HSPRG0
  *
  * 64-bit server:
  *     - SPRG0 unused (reserved for HV on Power4)
  *     - SPRG2 scratch for exception vectors
  *     - SPRG3 unused (user visible)
+ *      - HSPRG0 stores PACA in HV mode
+ *      - HSPRG1 scratch for "HV" exceptions
  *
  * 64-bit embedded
  *     - SPRG0 generic exception scratch
 
 #ifdef CONFIG_PPC_BOOK3S_64
 #define SPRN_SPRG_SCRATCH0     SPRN_SPRG2
+#define SPRN_SPRG_HPACA                SPRN_HSPRG0
+#define SPRN_SPRG_HSCRATCH0    SPRN_HSPRG1
+
+#define GET_PACA(rX)                                   \
+       BEGIN_FTR_SECTION_NESTED(66);                   \
+       mfspr   rX,SPRN_SPRG_PACA;                      \
+       FTR_SECTION_ELSE_NESTED(66);                    \
+       mfspr   rX,SPRN_SPRG_HPACA;                     \
+       ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+
+#define SET_PACA(rX)                                   \
+       BEGIN_FTR_SECTION_NESTED(66);                   \
+       mtspr   SPRN_SPRG_PACA,rX;                      \
+       FTR_SECTION_ELSE_NESTED(66);                    \
+       mtspr   SPRN_SPRG_HPACA,rX;                     \
+       ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
 #endif
 
 #ifdef CONFIG_PPC_BOOK3E_64
 #define SPRN_SPRG_TLB_EXFRAME  SPRN_SPRG2
 #define SPRN_SPRG_TLB_SCRATCH  SPRN_SPRG6
 #define SPRN_SPRG_GEN_SCRATCH  SPRN_SPRG0
+
+#define SET_PACA(rX)   mtspr   SPRN_SPRG_PACA,rX
+#define GET_PACA(rX)   mfspr   rX,SPRN_SPRG_PACA
+
 #endif
 
 #ifdef CONFIG_PPC_BOOK3S_32
 #define SPRN_SPRG_SCRATCH1     SPRN_SPRG1
 #endif
 
+
+
 /*
  * An mtfsf instruction with the L bit set. On CPUs that support this a
  * full 64bits of FPSCR is restored and on other CPUs the L bit is ignored.
 
 
 _STATIC(rtas_return_loc)
        /* relocation is off at this point */
-       mfspr   r4,SPRN_SPRG_PACA       /* Get PACA */
+       GET_PACA(r4)
        clrldi  r4,r4,2                 /* convert to realmode address */
 
        bcl     20,31,$+4
        REST_8GPRS(14, r1)              /* Restore the non-volatiles */
        REST_10GPRS(22, r1)             /* ditto */
 
-       mfspr   r13,SPRN_SPRG_PACA
+       GET_PACA(r13)
 
        ld      r4,_CCR(r1)
        mtcr    r4
 
        DO_KVM  0x300
        mtspr   SPRN_SPRG_SCRATCH0,r13
 BEGIN_FTR_SECTION
-       mfspr   r13,SPRN_SPRG_PACA
+       GET_PACA(r13)
        std     r9,PACA_EXSLB+EX_R9(r13)
        std     r10,PACA_EXSLB+EX_R10(r13)
        mfspr   r10,SPRN_DAR
        HMT_MEDIUM
        DO_KVM  0x380
        mtspr   SPRN_SPRG_SCRATCH0,r13
-       mfspr   r13,SPRN_SPRG_PACA              /* get paca address into r13 */
+       GET_PACA(r13)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_DAR
        std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
        HMT_MEDIUM
        DO_KVM  0x480
        mtspr   SPRN_SPRG_SCRATCH0,r13
-       mfspr   r13,SPRN_SPRG_PACA              /* get paca address into r13 */
+       GET_PACA(r13)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_SRR0            /* SRR0 is faulting address */
        std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
        beq-    1f
 END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
        mr      r9,r13
-       mfspr   r13,SPRN_SPRG_PACA
+       GET_PACA(r13)
        mfspr   r11,SPRN_SRR0
        ld      r12,PACAKBASE(r13)
        ld      r10,PACAKMSR(r13)
 
        mr      r3,r24                  /* not found, copy phys to r3    */
        b       .kexec_wait             /* next kernel might do better   */
 
-2:     mtspr   SPRN_SPRG_PACA,r13      /* Save vaddr of paca in an SPRG */
+2:     SET_PACA(r13)
 #ifdef CONFIG_PPC_BOOK3E
        addi    r12,r13,PACA_EXTLB      /* and TLB exc frame in another  */
        mtspr   SPRN_SPRG_TLB_EXFRAME,r12
        ld      r4,0(r4)                /* Get base vaddr of paca array */
        mulli   r13,r24,PACA_SIZE       /* Calculate vaddr of right paca */
        add     r13,r13,r4              /* for this processor.          */
-       mtspr   SPRN_SPRG_PACA,r13      /* Save vaddr of paca in an SPRG*/
+       SET_PACA(r13)                   /* Save vaddr of paca in an SPRG*/
 
        /* Mark interrupts soft and hard disabled (they might be enabled
         * in the PACA when doing hotplug)
 
 /* Put the paca pointer into r13 and SPRG_PACA */
 void setup_paca(struct paca_struct *new_paca)
 {
+       /* Setup r13 */
        local_paca = new_paca;
-       mtspr(SPRN_SPRG_PACA, local_paca);
+
 #ifdef CONFIG_PPC_BOOK3E
+       /* On Book3E, initialize the TLB miss exception frames */
        mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
+#else
+       /* In HV mode, we setup both HPACA and PACA to avoid problems
+        * if we do a GET_PACA() before the feature fixups have been
+        * applied
+        */
+       if (cpu_has_feature(CPU_FTR_HVMODE_206))
+               mtspr(SPRN_SPRG_HPACA, local_paca);
 #endif
+       mtspr(SPRN_SPRG_PACA, local_paca);
+
 }
 
 static int __initdata paca_size;
 
 
 #if defined(CONFIG_PPC_BOOK3S_64)
 
-#define LOAD_SHADOW_VCPU(reg)                          \
-       mfspr   reg, SPRN_SPRG_PACA
-
+#define LOAD_SHADOW_VCPU(reg)  GET_PACA(reg)                                   
 #define SHADOW_VCPU_OFF                PACA_KVM_SVCPU
 #define MSR_NOIRQ              MSR_KERNEL & ~(MSR_IR | MSR_DR)
 #define FUNC(name)             GLUE(.,name)