]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/kernel/head_fsl_booke.S
Merge branch 'next' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[~andy/linux] / arch / powerpc / kernel / head_fsl_booke.S
index de80e0f9a2bded4d802bdaf9c4f71a2e29add915..1f4434a3860885bc9fa33c821359731be7b7398d 100644 (file)
@@ -301,19 +301,20 @@ _ENTRY(__early_start)
 
 interrupt_base:
        /* Critical Input Interrupt */
-       CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
+       CRITICAL_EXCEPTION(0x0100, CRITICAL, CriticalInput, unknown_exception)
 
        /* Machine Check Interrupt */
 #ifdef CONFIG_E200
        /* no RFMCI, MCSRRs on E200 */
-       CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+       CRITICAL_EXCEPTION(0x0200, MACHINE_CHECK, MachineCheck, \
+                          machine_check_exception)
 #else
        MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
 #endif
 
        /* Data Storage Interrupt */
        START_EXCEPTION(DataStorage)
-       NORMAL_EXCEPTION_PROLOG
+       NORMAL_EXCEPTION_PROLOG(DATA_STORAGE)
        mfspr   r5,SPRN_ESR             /* Grab the ESR, save it, pass arg3 */
        stw     r5,_ESR(r11)
        mfspr   r4,SPRN_DEAR            /* Grab the DEAR, save it, pass arg2 */
@@ -328,7 +329,7 @@ interrupt_base:
        INSTRUCTION_STORAGE_EXCEPTION
 
        /* External Input Interrupt */
-       EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
+       EXCEPTION(0x0500, EXTERNAL, ExternalInput, do_IRQ, EXC_XFER_LITE)
 
        /* Alignment Interrupt */
        ALIGNMENT_EXCEPTION
@@ -342,32 +343,36 @@ interrupt_base:
 #else
 #ifdef CONFIG_E200
        /* E200 treats 'normal' floating point instructions as FP Unavail exception */
-       EXCEPTION(0x0800, FloatingPointUnavailable, program_check_exception, EXC_XFER_EE)
+       EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, \
+                 program_check_exception, EXC_XFER_EE)
 #else
-       EXCEPTION(0x0800, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, \
+                 unknown_exception, EXC_XFER_EE)
 #endif
 #endif
 
        /* System Call Interrupt */
        START_EXCEPTION(SystemCall)
-       NORMAL_EXCEPTION_PROLOG
+       NORMAL_EXCEPTION_PROLOG(SYSCALL)
        EXC_XFER_EE_LITE(0x0c00, DoSyscall)
 
        /* Auxiliary Processor Unavailable Interrupt */
-       EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x2900, AP_UNAVAIL, AuxillaryProcessorUnavailable, \
+                 unknown_exception, EXC_XFER_EE)
 
        /* Decrementer Interrupt */
        DECREMENTER_EXCEPTION
 
        /* Fixed Internal Timer Interrupt */
        /* TODO: Add FIT support */
-       EXCEPTION(0x3100, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x3100, FIT, FixedIntervalTimer, \
+                 unknown_exception, EXC_XFER_EE)
 
        /* Watchdog Timer Interrupt */
 #ifdef CONFIG_BOOKE_WDT
-       CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
+       CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, WatchdogException)
 #else
-       CRITICAL_EXCEPTION(0x3200, WatchdogTimer, unknown_exception)
+       CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, unknown_exception)
 #endif
 
        /* Data TLB Error Interrupt */
@@ -375,10 +380,16 @@ interrupt_base:
        mtspr   SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
        mfspr   r10, SPRN_SPRG_THREAD
        stw     r11, THREAD_NORMSAVE(0)(r10)
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+       mfspr   r11, SPRN_SRR1
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#endif
        stw     r12, THREAD_NORMSAVE(1)(r10)
        stw     r13, THREAD_NORMSAVE(2)(r10)
        mfcr    r13
        stw     r13, THREAD_NORMSAVE(3)(r10)
+       DO_KVM  BOOKE_INTERRUPT_DTLB_MISS SPRN_SRR1
        mfspr   r10, SPRN_DEAR          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -463,10 +474,16 @@ interrupt_base:
        mtspr   SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
        mfspr   r10, SPRN_SPRG_THREAD
        stw     r11, THREAD_NORMSAVE(0)(r10)
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+       mfspr   r11, SPRN_SRR1
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#endif
        stw     r12, THREAD_NORMSAVE(1)(r10)
        stw     r13, THREAD_NORMSAVE(2)(r10)
        mfcr    r13
        stw     r13, THREAD_NORMSAVE(3)(r10)
+       DO_KVM  BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR1
        mfspr   r10, SPRN_SRR0          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -538,36 +555,54 @@ interrupt_base:
 #ifdef CONFIG_SPE
        /* SPE Unavailable */
        START_EXCEPTION(SPEUnavailable)
-       NORMAL_EXCEPTION_PROLOG
+       NORMAL_EXCEPTION_PROLOG(SPE_UNAVAIL)
        bne     load_up_spe
        addi    r3,r1,STACK_FRAME_OVERHEAD
        EXC_XFER_EE_LITE(0x2010, KernelSPE)
 #else
-       EXCEPTION(0x2020, SPEUnavailable, unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x2020, SPE_UNAVAIL, SPEUnavailable, \
+                 unknown_exception, EXC_XFER_EE)
 #endif /* CONFIG_SPE */
 
        /* SPE Floating Point Data */
 #ifdef CONFIG_SPE
-       EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
+       EXCEPTION(0x2030, SPE_FP_DATA, SPEFloatingPointData, \
+                 SPEFloatingPointException, EXC_XFER_EE);
 
        /* SPE Floating Point Round */
-       EXCEPTION(0x2050, SPEFloatingPointRound, SPEFloatingPointRoundException, EXC_XFER_EE)
+       EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \
+                 SPEFloatingPointRoundException, EXC_XFER_EE)
 #else
-       EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
-       EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x2040, SPE_FP_DATA, SPEFloatingPointData, \
+                 unknown_exception, EXC_XFER_EE)
+       EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \
+                 unknown_exception, EXC_XFER_EE)
 #endif /* CONFIG_SPE */
 
        /* Performance Monitor */
-       EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
+       EXCEPTION(0x2060, PERFORMANCE_MONITOR, PerformanceMonitor, \
+                 performance_monitor_exception, EXC_XFER_STD)
 
-       EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD)
+       EXCEPTION(0x2070, DOORBELL, Doorbell, doorbell_exception, EXC_XFER_STD)
 
-       CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception)
+       CRITICAL_EXCEPTION(0x2080, DOORBELL_CRITICAL, \
+                          CriticalDoorbell, unknown_exception)
 
        /* Debug Interrupt */
        DEBUG_DEBUG_EXCEPTION
        DEBUG_CRIT_EXCEPTION
 
+       GUEST_DOORBELL_EXCEPTION
+
+       CRITICAL_EXCEPTION(0, GUEST_DBELL_CRIT, CriticalGuestDoorbell, \
+                          unknown_exception)
+
+       /* Hypercall */
+       EXCEPTION(0, HV_SYSCALL, Hypercall, unknown_exception, EXC_XFER_EE)
+
+       /* Embedded Hypervisor Privilege */
+       EXCEPTION(0, HV_PRIV, Ehvpriv, unknown_exception, EXC_XFER_EE)
+
 /*
  * Local functions
  */
@@ -871,8 +906,31 @@ _GLOBAL(__setup_e500mc_ivors)
        mtspr   SPRN_IVOR36,r3
        li      r3,CriticalDoorbell@l
        mtspr   SPRN_IVOR37,r3
+
+       /*
+        * We only want to touch IVOR38-41 if we're running on hardware
+        * that supports category E.HV.  The architectural way to determine
+        * this is MMUCFG[LPIDSIZE].
+        */
+       mfspr   r3, SPRN_MMUCFG
+       andis.  r3, r3, MMUCFG_LPIDSIZE@h
+       beq     no_hv
+       li      r3,GuestDoorbell@l
+       mtspr   SPRN_IVOR38,r3
+       li      r3,CriticalGuestDoorbell@l
+       mtspr   SPRN_IVOR39,r3
+       li      r3,Hypercall@l
+       mtspr   SPRN_IVOR40,r3
+       li      r3,Ehvpriv@l
+       mtspr   SPRN_IVOR41,r3
+skip_hv_ivors:
        sync
        blr
+no_hv:
+       lwz     r3, CPU_SPEC_FEATURES(r5)
+       rlwinm  r3, r3, 0, ~CPU_FTR_EMB_HV
+       stw     r3, CPU_SPEC_FEATURES(r5)
+       b       skip_hv_ivors
 
 #ifdef CONFIG_SPE
 /*