Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[sfrench/cifs-2.6.git] / arch / microblaze / kernel / entry.S
index 04267ca949f0c5db253e5dc7b0be59eb91f8ad71..304882e56459b70d90b661622b54066452a38d74 100644 (file)
  */
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
        .macro  clear_bip
-       msrclr  r11, MSR_BIP
-       nop
+       msrclr  r0, MSR_BIP
        .endm
 
        .macro  set_bip
-       msrset  r11, MSR_BIP
-       nop
+       msrset  r0, MSR_BIP
        .endm
 
        .macro  clear_eip
-       msrclr  r11, MSR_EIP
-       nop
+       msrclr  r0, MSR_EIP
        .endm
 
        .macro  set_ee
-       msrset  r11, MSR_EE
-       nop
+       msrset  r0, MSR_EE
        .endm
 
        .macro  disable_irq
-       msrclr  r11, MSR_IE
-       nop
+       msrclr  r0, MSR_IE
        .endm
 
        .macro  enable_irq
-       msrset  r11, MSR_IE
-       nop
+       msrset  r0, MSR_IE
        .endm
 
        .macro  set_ums
-       msrset  r11, MSR_UMS
-       nop
-       msrclr  r11, MSR_VMS
-       nop
+       msrset  r0, MSR_UMS
+       msrclr  r0, MSR_VMS
        .endm
 
        .macro  set_vms
-       msrclr  r11, MSR_UMS
-       nop
-       msrset  r11, MSR_VMS
-       nop
+       msrclr  r0, MSR_UMS
+       msrset  r0, MSR_VMS
+       .endm
+
+       .macro  clear_ums
+       msrclr  r0, MSR_UMS
        .endm
 
        .macro  clear_vms_ums
-       msrclr  r11, MSR_VMS | MSR_UMS
-       nop
+       msrclr  r0, MSR_VMS | MSR_UMS
        .endm
 #else
        .macro  clear_bip
        mfs     r11, rmsr
-       nop
        andi    r11, r11, ~MSR_BIP
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  set_bip
        mfs     r11, rmsr
-       nop
        ori     r11, r11, MSR_BIP
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  clear_eip
        mfs     r11, rmsr
-       nop
        andi    r11, r11, ~MSR_EIP
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  set_ee
        mfs     r11, rmsr
-       nop
        ori     r11, r11, MSR_EE
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  disable_irq
        mfs     r11, rmsr
-       nop
        andi    r11, r11, ~MSR_IE
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  enable_irq
        mfs     r11, rmsr
-       nop
        ori     r11, r11, MSR_IE
        mts     rmsr, r11
-       nop
        .endm
 
        .macro set_ums
        mfs     r11, rmsr
-       nop
        ori     r11, r11, MSR_VMS
        andni   r11, r11, MSR_UMS
        mts     rmsr, r11
-       nop
        .endm
 
        .macro  set_vms
        mfs     r11, rmsr
-       nop
        ori     r11, r11, MSR_VMS
        andni   r11, r11, MSR_UMS
        mts     rmsr, r11
-       nop
+       .endm
+
+       .macro  clear_ums
+       mfs     r11, rmsr
+       andni   r11, r11, MSR_UMS
+       mts     rmsr,r11
        .endm
 
        .macro  clear_vms_ums
        mfs     r11, rmsr
-       nop
        andni   r11, r11, (MSR_VMS|MSR_UMS)
        mts     rmsr,r11
-       nop
        .endm
 #endif
 
        swi     r30, r1, PTO+PT_R30;                                    \
        swi     r31, r1, PTO+PT_R31;    /* Save current task reg */     \
        mfs     r11, rmsr;              /* save MSR */                  \
-       nop;                                                            \
        swi     r11, r1, PTO+PT_MSR;
 
 #define RESTORE_REGS \
        lwi     r11, r1, PTO+PT_MSR;                                    \
        mts     rmsr , r11;                                             \
-       nop;                                                            \
        lwi     r2, r1, PTO+PT_R2;      /* restore SDA */               \
        lwi     r3, r1, PTO+PT_R3;                                      \
        lwi     r4, r1, PTO+PT_R4;                                      \
        lwi     r30, r1, PTO+PT_R30;                                    \
        lwi     r31, r1, PTO+PT_R31;    /* Restore cur task reg */
 
+#define SAVE_STATE     \
+       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */     \
+       /* See if already in kernel mode.*/                             \
+       mfs     r1, rmsr;                                               \
+       andi    r1, r1, MSR_UMS;                                        \
+       bnei    r1, 1f;                                         \
+       /* Kernel-mode state save.  */                                  \
+       /* Reload kernel stack-ptr. */                                  \
+       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP));                      \
+       /* FIXME: I can add these two lines to one */                   \
+       /* tophys(r1,r1); */                                            \
+       /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
+       addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+       SAVE_REGS                                                       \
+       brid    2f;                                                     \
+       swi     r1, r1, PTO+PT_MODE;                                    \
+1:     /* User-mode state save.  */                                    \
+       lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
+       tophys(r1,r1);                                                  \
+       lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */       \
+       /* MS these three instructions can be added to one */           \
+       /* addik        r1, r1, THREAD_SIZE; */                         \
+       /* tophys(r1,r1); */                                            \
+       /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
+       addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+       SAVE_REGS                                                       \
+       lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
+       swi     r11, r1, PTO+PT_R1; /* Store user SP.  */               \
+       swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */         \
+       /* MS: I am clearing UMS even in case when I come from kernel space */ \
+       clear_ums;                                                      \
+2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+
 .text
 
 /*
  * are masked. This is nice, means we don't have to CLI before state save
  */
 C_ENTRY(_user_exception):
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
        addi    r14, r14, 4     /* return address is 4 byte after call */
-       swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */
-
-       mfs     r11, rmsr
-       nop
-       andi    r11, r11, MSR_UMS
-       bnei    r11, 1f
-
-/* Kernel-mode state save - kernel execve */
-       lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
-       tophys(r1,r11);
-       swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
-
-       addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
-       SAVE_REGS
-
-       addi    r11, r0, 1;             /* Was in kernel-mode. */
-       swi     r11, r1, PTO+PT_MODE; /* pt_regs -> kernel mode */
-       brid    2f;
-       nop;                            /* Fill delay slot */
+       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
 
-/* User-mode state save.  */
-1:
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
        tophys(r1,r1);
        lwi     r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
-/* calculate kernel stack pointer from task struct 8k */
-       addik   r1, r1, THREAD_SIZE;
-       tophys(r1,r1);
-
-       addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+       /* MS these three instructions can be added to one */
+       /* addik        r1, r1, THREAD_SIZE; */
+       /* tophys(r1,r1); */
+       /* addik        r1, r1, -STATE_SAVE_SIZE; */
+       addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
        SAVE_REGS
 
-       swi     r0, r1, PTO+PT_MODE;                    /* Was in user-mode. */
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1;             /* Store user SP.  */
-2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+       clear_ums;
+       lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
        /* Save away the syscall number.  */
        swi     r12, r1, PTO+PT_R0;
        tovirt(r1,r1)
@@ -321,10 +310,8 @@ C_ENTRY(_user_exception):
  * register should point to the location where
  * the called function should return.  [note that MAKE_SYS_CALL uses label 1] */
 
-       # Step into virtual mode.
-       set_vms;
-       addik   r11, r0, 3f
-       rtid    r11, 0
+       /* Step into virtual mode */
+       rtbd    r0, 3f
        nop
 3:
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
@@ -373,10 +360,8 @@ C_ENTRY(_user_exception):
 
        /* The syscall number is invalid, return an error.  */
 5:
+       rtsd    r15, 8;         /* looks like a normal subroutine return */
        addi    r3, r0, -ENOSYS;
-       rtsd    r15,8;          /* looks like a normal subroutine return */
-       or      r0, r0, r0
-
 
 /* Entry point used to return from a syscall/trap */
 /* We re-enable BIP bit before state restore */
@@ -384,9 +369,6 @@ C_ENTRY(ret_from_trap):
        swi     r3, r1, PTO + PT_R3
        swi     r4, r1, PTO + PT_R4
 
-       lwi     r11, r1, PTO+PT_MODE;
-/* See if returning to kernel mode, if so, skip resched &c.  */
-       bnei    r11, 2f;
        /* We're returning to user mode, so check for various conditions that
         * trigger rescheduling. */
        /* FIXME: Restructure all these flag checks. */
@@ -429,16 +411,6 @@ C_ENTRY(ret_from_trap):
        RESTORE_REGS;
        addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
        lwi     r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
-       bri     6f;
-
-/* Return to kernel state.  */
-2:     set_bip;                        /*  Ints masked for state restore */
-       VM_OFF;
-       tophys(r1,r1);
-       RESTORE_REGS;
-       addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
-       tovirt(r1,r1);
-6:
 TRAP_return:           /* Make global symbol for debugging */
        rtbd    r14, 0; /* Instructions to return from an IRQ */
        nop;
@@ -453,9 +425,8 @@ C_ENTRY(sys_fork_wrapper):
        addik   r7, r1, PTO                     /* Arg 2: parent context */
        add     r8. r0, r0                      /* Arg 3: (unused) */
        add     r9, r0, r0;                     /* Arg 4: (unused) */
-       add     r10, r0, r0;                    /* Arg 5: (unused) */
        brid    do_fork         /* Do real work (tail-call) */
-       nop;
+       add     r10, r0, r0;                    /* Arg 5: (unused) */
 
 /* This the initial entry point for a new child thread, with an appropriate
    stack in place that makes it look the the child is in the middle of an
@@ -466,9 +437,8 @@ C_ENTRY(ret_from_fork):
        bralid  r15, schedule_tail; /* ...which is schedule_tail's arg */
        add     r3, r5, r0;     /* switch_thread returns the prev task */
                                /* ( in the delay slot ) */
-       add     r3, r0, r0;     /* Child's fork call should return 0. */
        brid    ret_from_trap;  /* Do normal trap return */
-       nop;
+       add     r3, r0, r0;     /* Child's fork call should return 0. */
 
 C_ENTRY(sys_vfork):
        brid    microblaze_vfork        /* Do real work (tail-call) */
@@ -480,21 +450,18 @@ C_ENTRY(sys_clone):
 1:     addik   r7, r1, PTO;                    /* Arg 2: parent context */
        add     r8, r0, r0;                     /* Arg 3: (unused) */
        add     r9, r0, r0;                     /* Arg 4: (unused) */
-       add     r10, r0, r0;                    /* Arg 5: (unused) */
        brid    do_fork         /* Do real work (tail-call) */
-       nop;
+       add     r10, r0, r0;                    /* Arg 5: (unused) */
 
 C_ENTRY(sys_execve):
-       addik   r8, r1, PTO;            /* add user context as 4th arg */
        brid    microblaze_execve;      /* Do real work (tail-call).*/
-       nop;
+       addik   r8, r1, PTO;            /* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
        swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
        swi     r4, r1, PTO+PT_R4;
-       addik   r5, r1, PTO;            /* add user context as 1st arg */
        brlid   r15, sys_rt_sigreturn   /* Do real work */
-       nop;
+       addik   r5, r1, PTO;            /* add user context as 1st arg */
        lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
        lwi     r4, r1, PTO+PT_R4;
        bri ret_from_trap /* fall through will not work here due to align */
@@ -503,71 +470,23 @@ C_ENTRY(sys_rt_sigreturn_wrapper):
 /*
  * HW EXCEPTION rutine start
  */
-
-#define SAVE_STATE     \
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */     \
-       swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */  \
-       /* See if already in kernel mode.*/                             \
-       mfs     r11, rmsr;                                              \
-       nop;                                                            \
-       andi    r11, r11, MSR_UMS;                                      \
-       bnei    r11, 1f;                                                \
-       /* Kernel-mode state save.  */                                  \
-       /* Reload kernel stack-ptr. */                                  \
-       lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
-       tophys(r1,r11);                                                 \
-       swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */       \
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
-       addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
-       SAVE_REGS                                                       \
-       /* PC, before IRQ/trap - this is one instruction above */       \
-       swi     r17, r1, PTO+PT_PC;                                     \
-                                                                       \
-       addi    r11, r0, 1;             /* Was in kernel-mode.  */      \
-       swi     r11, r1, PTO+PT_MODE;                                   \
-       brid    2f;                                                     \
-       nop;                            /* Fill delay slot */           \
-1:     /* User-mode state save.  */                                    \
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
-       lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
-       tophys(r1,r1);                                                  \
-       lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */       \
-       addik   r1, r1, THREAD_SIZE;    /* calculate kernel stack pointer */\
-       tophys(r1,r1);                                                  \
-                                                                       \
-       addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
-       SAVE_REGS                                                       \
-       /* PC, before IRQ/trap - this is one instruction above FIXME*/  \
-       swi     r17, r1, PTO+PT_PC;                                     \
-                                                                       \
-       swi     r0, r1, PTO+PT_MODE; /* Was in user-mode.  */           \
-       lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
-       swi     r11, r1, PTO+PT_R1; /* Store user SP.  */               \
-2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));        \
-       /* Save away the syscall number.  */                            \
-       swi     r0, r1, PTO+PT_R0;                                      \
-       tovirt(r1,r1)
-
 C_ENTRY(full_exception_trap):
        /* adjust exception address for privileged instruction
         * for finding where is it */
        addik   r17, r17, -4
        SAVE_STATE /* Save registers */
+       /* PC, before IRQ/trap - this is one instruction above */
+       swi     r17, r1, PTO+PT_PC;
+       tovirt(r1,r1)
        /* FIXME this can be store directly in PT_ESR reg.
         * I tested it but there is a fault */
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
        addik   r15, r0, ret_from_exc - 8
-       addik   r5, r1, PTO              /* parameter struct pt_regs * regs */
        mfs     r6, resr
-       nop
        mfs     r7, rfsr;               /* save FSR */
-       nop
        mts     rfsr, r0;       /* Clear sticky fsr */
-       nop
-       addik   r12, r0, full_exception
-       set_vms;
-       rted    r12, 0;
-       nop;
+       rted    r0, full_exception
+       addik   r5, r1, PTO              /* parameter struct pt_regs * regs */
 
 /*
  * Unaligned data trap.
@@ -592,17 +511,15 @@ C_ENTRY(unaligned_data_trap):
        set_ee;
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        SAVE_STATE              /* Save registers.*/
+       /* PC, before IRQ/trap - this is one instruction above */
+       swi     r17, r1, PTO+PT_PC;
+       tovirt(r1,r1)
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
        addik   r15, r0, ret_from_exc-8
        mfs     r3, resr                /* ESR */
-       nop
        mfs     r4, rear                /* EAR */
-       nop
+       rtbd    r0, _unaligned_data_exception
        addik   r7, r1, PTO             /* parameter struct pt_regs * regs */
-       addik   r12, r0, _unaligned_data_exception
-       set_vms;
-       rtbd    r12, 0; /* interrupts enabled */
-       nop;
 
 /*
  * Page fault traps.
@@ -624,34 +541,31 @@ C_ENTRY(unaligned_data_trap):
 /* data and intruction trap - which is choose is resolved int fault.c */
 C_ENTRY(page_fault_data_trap):
        SAVE_STATE              /* Save registers.*/
+       /* PC, before IRQ/trap - this is one instruction above */
+       swi     r17, r1, PTO+PT_PC;
+       tovirt(r1,r1)
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
        addik   r15, r0, ret_from_exc-8
-       addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
        mfs     r6, rear                /* parameter unsigned long address */
-       nop
        mfs     r7, resr                /* parameter unsigned long error_code */
-       nop
-       addik   r12, r0, do_page_fault
-       set_vms;
-       rted    r12, 0; /* interrupts enabled */
-       nop;
+       rted    r0, do_page_fault
+       addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
 
 C_ENTRY(page_fault_instr_trap):
        SAVE_STATE              /* Save registers.*/
+       /* PC, before IRQ/trap - this is one instruction above */
+       swi     r17, r1, PTO+PT_PC;
+       tovirt(r1,r1)
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
        addik   r15, r0, ret_from_exc-8
-       addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
        mfs     r6, rear                /* parameter unsigned long address */
-       nop
        ori     r7, r0, 0               /* parameter unsigned long error_code */
-       addik   r12, r0, do_page_fault
-       set_vms;
-       rted    r12, 0; /* interrupts enabled */
-       nop;
+       rted    r0, do_page_fault
+       addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
 
 /* Entry point used to return from an exception.  */
 C_ENTRY(ret_from_exc):
-       lwi     r11, r1, PTO+PT_MODE;
+       lwi     r11, r1, PTO + PT_MODE;
        bnei    r11, 2f;                /* See if returning to kernel mode, */
                                        /* ... if so, skip resched &c.  */
 
@@ -726,34 +640,23 @@ C_ENTRY(_interrupt):
 /* MS: we are in physical address */
 /* Save registers, switch to proper stack, convert SP to virtual.*/
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
-       swi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
        /* MS: See if already in kernel mode. */
-       mfs     r11, rmsr
+       mfs     r1, rmsr
        nop
-       andi    r11, r11, MSR_UMS
-       bnei    r11, 1f
+       andi    r1, r1, MSR_UMS
+       bnei    r1, 1f
 
 /* Kernel-mode state save. */
-       or      r11, r1, r0
-       tophys(r1,r11); /* MS: I have in r1 physical address where stack is */
-/* MS: Save original SP - position PT_R1 to next stack frame 4 *1 - 152*/
-       swi     r11, r1, (PT_R1 - PT_SIZE);
-/* MS: restore r11 because of saving in SAVE_REGS */
-       lwi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
+       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+       tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
        /* save registers */
 /* MS: Make room on the stack -> activation record */
        addik   r1, r1, -STATE_SAVE_SIZE;
        SAVE_REGS
-       /* MS: store mode */
-       addi    r11, r0, 1; /* MS: Was in kernel-mode. */
-       swi     r11, r1, PTO + PT_MODE; /* MS: and save it */
        brid    2f;
-       nop; /* MS: Fill delay slot */
-
+       swi     r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
 1:
 /* User-mode state save. */
-/* MS: restore r11 -> FIXME move before SAVE_REG */
-       lwi     r11, r0, TOPHYS(PER_CPU(R11_SAVE));
  /* MS: get the saved current */
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
        tophys(r1,r1);
@@ -767,16 +670,13 @@ C_ENTRY(_interrupt):
        swi     r0, r1, PTO + PT_MODE;
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1;
+       clear_ums;
 2:
        lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
-       swi     r0, r1, PTO + PT_R0;
        tovirt(r1,r1)
-       addik   r5, r1, PTO;
-       set_vms;
-       addik   r11, r0, do_IRQ;
        addik   r15, r0, irq_call;
-irq_call:rtbd  r11, 0;
-       nop;
+irq_call:rtbd  r0, do_IRQ;
+       addik   r5, r1, PTO;
 
 /* MS: we are in virtual mode */
 ret_from_irq:
@@ -845,40 +745,55 @@ IRQ_return: /* MS: Make global symbol for debugging */
        nop
 
 /*
- * `Debug' trap
- *  We enter dbtrap in "BIP" (breakpoint) mode.
- *  So we exit the breakpoint mode with an 'rtbd' and proceed with the
- *  original dbtrap.
- *  however, wait to save state first
+ * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
+ * and call handling function with saved pt_regs
  */
 C_ENTRY(_debug_exception):
        /* BIP bit is set on entry, no interrupts can occur */
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
 
-       swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */
-       set_bip;        /*equalize initial state for all possible entries*/
-       clear_eip;
-       enable_irq;
-       mfs     r11, rmsr
+       mfs     r1, rmsr
        nop
-       andi    r11, r11, MSR_UMS
-       bnei    r11, 1f
-       /* Kernel-mode state save.  */
-       lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
-       tophys(r1,r11);
-       swi     r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
+       andi    r1, r1, MSR_UMS
+       bnei    r1, 1f
+/* MS: Kernel-mode state save - kgdb */
+       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 
-       addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+       /* BIP bit is set on entry, no interrupts can occur */
+       addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
        SAVE_REGS;
+       /* save all regs to pt_reg structure */
+       swi     r0, r1, PTO+PT_R0;      /* R0 must be saved too */
+       swi     r14, r1, PTO+PT_R14     /* rewrite saved R14 value */
+       swi     r16, r1, PTO+PT_R16
+       swi     r16, r1, PTO+PT_PC; /* PC and r16 are the same */
+       swi     r17, r1, PTO+PT_R17
+       /* save special purpose registers to pt_regs */
+       mfs     r11, rear;
+       swi     r11, r1, PTO+PT_EAR;
+       mfs     r11, resr;
+       swi     r11, r1, PTO+PT_ESR;
+       mfs     r11, rfsr;
+       swi     r11, r1, PTO+PT_FSR;
+
+       /* stack pointer is in physical address at it is decrease
+        * by STATE_SAVE_SIZE but we need to get correct R1 value */
+       addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
+       swi     r11, r1, PTO+PT_R1
+       /* MS: r31 - current pointer isn't changed */
+       tovirt(r1,r1)
+#ifdef CONFIG_KGDB
+       addi    r5, r1, PTO /* pass pt_reg address as the first arg */
+       la      r15, r0, dbtrap_call; /* return address */
+       rtbd    r0, microblaze_kgdb_break
+       nop;
+#endif
+       /* MS: Place handler for brki from kernel space if KGDB is OFF.
+        * It is very unlikely that another brki instruction is called. */
+       bri 0
 
-       addi    r11, r0, 1;             /* Was in kernel-mode.  */
-       swi     r11, r1, PTO + PT_MODE;
-       brid    2f;
-       nop;                            /* Fill delay slot */
-1:      /* User-mode state save.  */
-       lwi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
-       lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+/* MS: User-mode state save - gdb */
+1:     lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
        tophys(r1,r1);
        lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */
        addik   r1, r1, THREAD_SIZE;    /* calculate kernel stack pointer */
@@ -886,38 +801,35 @@ C_ENTRY(_debug_exception):
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
        SAVE_REGS;
-
-       swi     r0, r1, PTO+PT_MODE; /* Was in user-mode.  */
+       swi     r17, r1, PTO+PT_R17;
+       swi     r16, r1, PTO+PT_R16;
+       swi     r16, r1, PTO+PT_PC;     /* Save LP */
+       swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1; /* Store user SP.  */
-2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
-       /* Save away the syscall number.  */
-       swi     r0, r1, PTO+PT_R0;
+       lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
        tovirt(r1,r1)
-
        set_vms;
-       addi    r5, r0, SIGTRAP              /* send the trap signal */
-       add     r6, r0, CURRENT_TASK; /* Get current task ptr into r11 */
-       addk    r7, r0, r0                   /* 3rd param zero */
-dbtrap_call:   rtbd    r0, send_sig;
+       addik   r5, r1, PTO;
        addik   r15, r0, dbtrap_call;
+dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
+       rtbd    r0, sw_exception
+       nop
 
-       set_bip;                        /*  Ints masked for state restore*/
-       lwi     r11, r1, PTO+PT_MODE;
+       /* MS: The first instruction for the second part of the gdb/kgdb */
+       set_bip; /* Ints masked for state restore */
+       lwi     r11, r1, PTO + PT_MODE;
        bnei    r11, 2f;
-
+/* MS: Return to user space - gdb */
        /* Get current task ptr into r11 */
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
        andi    r11, r11, _TIF_NEED_RESCHED;
        beqi    r11, 5f;
 
-/* Call the scheduler before returning from a syscall/trap. */
-
+       /* Call the scheduler before returning from a syscall/trap. */
        bralid  r15, schedule;  /* Call scheduler */
        nop;                            /* delay slot */
-       /* XXX Is PT_DTRACE handling needed here? */
-       /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here.  */
 
        /* Maybe handle a signal */
 5:     lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
@@ -925,50 +837,40 @@ dbtrap_call:      rtbd    r0, send_sig;
        andi    r11, r11, _TIF_SIGPENDING;
        beqi    r11, 1f;                /* Signals to handle, handle them */
 
-/* Handle a signal return; Pending signals should be in r18.  */
-       /* Not all registers are saved by the normal trap/interrupt entry
-          points (for instance, call-saved registers (because the normal
-          C-compiler calling sequence in the kernel makes sure they're
-          preserved), and call-clobbered registers in the case of
-          traps), but signal handlers may want to examine or change the
-          complete register state.  Here we save anything not saved by
-          the normal entry sequence, so that it may be safely restored
-          (in a possibly modified form) after do_signal returns.  */
-
        addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
        addi  r7, r0, 0;        /* Arg 3: int in_syscall */
        bralid  r15, do_signal; /* Handle any signals */
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
 
-
 /* Finally, return to user state.  */
-1:
-       swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
+1:     swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
        VM_OFF;
        tophys(r1,r1);
-
+       /* MS: Restore all regs */
        RESTORE_REGS
-       addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
-
-
-       lwi     r1, r1, PT_R1 - PT_SIZE;
-                                       /* Restore user stack pointer. */
-       bri     6f;
+       lwi     r17, r1, PTO+PT_R17;
+       lwi     r16, r1, PTO+PT_R16;
+       addik   r1, r1, STATE_SAVE_SIZE  /* Clean up stack space */
+       lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
+DBTRAP_return_user: /* MS: Make global symbol for debugging */
+       rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
+       nop;
 
-/* Return to kernel state.  */
+/* MS: Return to kernel state - kgdb */
 2:     VM_OFF;
        tophys(r1,r1);
+       /* MS: Restore all regs */
        RESTORE_REGS
-       addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
-
+       lwi     r14, r1, PTO+PT_R14;
+       lwi     r16, r1, PTO+PT_PC;
+       lwi     r17, r1, PTO+PT_R17;
+       addik   r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
        tovirt(r1,r1);
-6:
-DBTRAP_return:         /* Make global symbol for debugging */
-       rtbd    r14, 0; /* Instructions to return from an IRQ */
+DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
+       rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
        nop;
 
 
-
 ENTRY(_switch_to)
        /* prepare return value */
        addk    r3, r0, CURRENT_TASK
@@ -1003,16 +905,12 @@ ENTRY(_switch_to)
        swi     r30, r11, CC_R30
        /* special purpose registers */
        mfs     r12, rmsr
-       nop
        swi     r12, r11, CC_MSR
        mfs     r12, rear
-       nop
        swi     r12, r11, CC_EAR
        mfs     r12, resr
-       nop
        swi     r12, r11, CC_ESR
        mfs     r12, rfsr
-       nop
        swi     r12, r11, CC_FSR
 
        /* update r31, the current-give me pointer to task which will be next */
@@ -1051,10 +949,8 @@ ENTRY(_switch_to)
        /* special purpose registers */
        lwi     r12, r11, CC_FSR
        mts     rfsr, r12
-       nop
        lwi     r12, r11, CC_MSR
        mts     rmsr, r12
-       nop
 
        rtsd    r15, 8
        nop
@@ -1062,15 +958,6 @@ ENTRY(_switch_to)
 ENTRY(_reset)
        brai    0x70; /* Jump back to FS-boot */
 
-ENTRY(_break)
-       mfs     r5, rmsr
-       nop
-       swi     r5, r0, 0x250 + TOPHYS(r0_ram)
-       mfs     r5, resr
-       nop
-       swi     r5, r0, 0x254 + TOPHYS(r0_ram)
-       bri     0
-
        /* These are compiled and loaded into high memory, then
         * copied into place in mach_early_setup */
        .section        .init.ivt, "ax"
@@ -1082,12 +969,9 @@ ENTRY(_break)
        nop
        brai    TOPHYS(_user_exception); /* syscall handler */
        brai    TOPHYS(_interrupt);     /* Interrupt handler */
-       brai    TOPHYS(_break);         /* nmi trap handler */
+       brai    TOPHYS(_debug_exception);       /* debug trap handler */
        brai    TOPHYS(_hw_exception_handler);  /* HW exception handler */
 
-       .org    0x60
-       brai    TOPHYS(_debug_exception);       /* debug trap handler*/
-
 .section .rodata,"a"
 #include "syscall_table.S"