]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/microblaze/kernel/entry.S
microblaze: Put together addik instructions
[mv-sheeva.git] / arch / microblaze / kernel / entry.S
index f5fe220954b0e636cbaec5d728f3bb406ad17160..e7abf7426c8cbe122e497db9e78b11468cb089b8 100644 (file)
  */
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
        .macro  clear_bip
-       msrclr  r11, MSR_BIP
+       msrclr  r0, MSR_BIP
        nop
        .endm
 
        .macro  set_bip
-       msrset  r11, MSR_BIP
+       msrset  r0, MSR_BIP
        nop
        .endm
 
        .macro  clear_eip
-       msrclr  r11, MSR_EIP
+       msrclr  r0, MSR_EIP
        nop
        .endm
 
        .macro  set_ee
-       msrset  r11, MSR_EE
+       msrset  r0, MSR_EE
        nop
        .endm
 
        .macro  disable_irq
-       msrclr  r11, MSR_IE
+       msrclr  r0, MSR_IE
        nop
        .endm
 
        .macro  enable_irq
-       msrset  r11, MSR_IE
+       msrset  r0, MSR_IE
        nop
        .endm
 
        .macro  set_ums
-       msrset  r11, MSR_UMS
+       msrset  r0, MSR_UMS
        nop
-       msrclr  r11, MSR_VMS
+       msrclr  r0, MSR_VMS
        nop
        .endm
 
        .macro  set_vms
-       msrclr  r11, MSR_UMS
+       msrclr  r0, MSR_UMS
        nop
-       msrset  r11, MSR_VMS
+       msrset  r0, MSR_VMS
+       nop
+       .endm
+
+       .macro  clear_ums
+       msrclr  r0, MSR_UMS
        nop
        .endm
 
        .macro  clear_vms_ums
-       msrclr  r11, MSR_VMS | MSR_UMS
+       msrclr  r0, MSR_VMS | MSR_UMS
        nop
        .endm
 #else
        nop
        .endm
 
+       .macro  clear_ums
+       mfs     r11, rmsr
+       nop
+       andni   r11, r11, MSR_UMS
+       mts     rmsr,r11
+       nop
+       .endm
+
        .macro  clear_vms_ums
        mfs     r11, rmsr
        nop
        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;                                               \
+       nop;                                                            \
+       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
 
 /*
 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 */
 
-       lwi     r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
-       beqi    r11, 1f;                /* Jump ahead if coming from user */
-/* 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 */
+       mfs     r1, rmsr
+       nop
+       andi    r1, r1, MSR_UMS
+       bnei    r1, 1f
+
+/* Kernel-mode state save - kernel execve */
+       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+       tophys(r1,r1);
 
        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 */
+       swi     r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
        brid    2f;
        nop;                            /* Fill delay slot */
 
 /* 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 */
@@ -304,11 +349,9 @@ C_ENTRY(_user_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     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.  */
-       addi    r11, r0, 1;
-       swi     r11, r0, TOPHYS(PER_CPU(KM));   /* Now we're in kernel-mode.  */
 2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
        /* Save away the syscall number.  */
        swi     r12, r1, PTO+PT_R0;
@@ -367,24 +410,21 @@ C_ENTRY(_user_exception):
        # Find and jump into the syscall handler.
        lwi     r12, r12, sys_call_table
        /* where the trap should return need -8 to adjust for rtsd r15, 8 */
-       la      r15, r0, ret_from_trap-8
+       addi    r15, r0, ret_from_trap-8
        bra     r12
 
        /* 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 */
 C_ENTRY(ret_from_trap):
-       set_bip;                        /*  Ints masked for state restore*/
        swi     r3, r1, PTO + PT_R3
        swi     r4, r1, PTO + PT_R4
 
-       lwi     r11, r1, PTO+PT_MODE;
+       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
@@ -416,14 +456,13 @@ C_ENTRY(ret_from_trap):
        andi    r11, r11, _TIF_SIGPENDING;
        beqi    r11, 1f;                /* Signals to handle, handle them */
 
-       la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
+       addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
        addi    r7, r0, 1;              /* 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     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
+1:     set_bip;                        /*  Ints masked for state restore */
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
        VM_OFF;
        tophys(r1,r1);
@@ -433,7 +472,8 @@ C_ENTRY(ret_from_trap):
        bri     6f;
 
 /* Return to kernel state.  */
-2:     VM_OFF;
+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.  */
@@ -450,12 +490,11 @@ TRAP_return:              /* Make global symbol for debugging */
 C_ENTRY(sys_fork_wrapper):
        addi    r5, r0, SIGCHLD                 /* Arg 0: flags */
        lwi     r6, r1, PTO+PT_R1       /* Arg 1: child SP (use parent's) */
-       la      r7, r1, PTO                     /* Arg 2: parent context */
+       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,35 +505,31 @@ 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) */
-       la      r5, r1, PTO
+       addik   r5, r1, PTO
 
 C_ENTRY(sys_clone):
        bnei    r6, 1f;                 /* See if child SP arg (arg 1) is 0. */
        lwi     r6, r1, PTO + PT_R1;    /* If so, use paret's stack ptr */
-1:     add     r10, r0, r9;            /* Arg 6: (child_tidptr) */
-       add     r9, r0, r8;             /* Arg 5: (parent_tidptr) */
-       add     r8, r0, r7;             /* Arg 4: (stack_size) */
-       la      r7, r1, PTO;            /* Arg 3: pt_regs  */
-       brid    do_fork                 /* Do real work (tail-call) */
-       nop
+1:     addik   r7, r1, PTO;                    /* Arg 2: parent context */
+       add     r8, r0, r0;                     /* Arg 3: (unused) */
+       add     r9, r0, r0;                     /* Arg 4: (unused) */
+       brid    do_fork         /* Do real work (tail-call) */
+       add     r10, r0, r0;                    /* Arg 5: (unused) */
 
 C_ENTRY(sys_execve):
-       la      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;
-       la      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,75 +538,26 @@ C_ENTRY(sys_rt_sigreturn_wrapper):
 /*
  * HW EXCEPTION rutine start
  */
-
-#define SAVE_STATE     \
-       swi     r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */  \
-       set_bip;        /*equalize initial state for all possible entries*/\
-       clear_eip;                                                      \
-       enable_irq;                                                     \
-       set_ee;                                                         \
-       /* See if already in kernel mode.*/                             \
-       lwi     r11, r0, TOPHYS(PER_CPU(KM));                           \
-       beqi    r11, 1f;                /* Jump ahead if coming from user */\
-       /* 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.  */               \
-       addi    r11, r0, 1;                                             \
-       swi     r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\
-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):
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
        /* 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 */
-       la      r15, r0, ret_from_exc - 8
-       la      r5, r1, PTO              /* parameter struct pt_regs * regs */
+       addik   r15, r0, ret_from_exc - 8
        mfs     r6, resr
        nop
        mfs     r7, rfsr;               /* save FSR */
        nop
        mts     rfsr, r0;       /* Clear sticky fsr */
        nop
-       la      r12, r0, full_exception
-       set_vms;
-       rtbd    r12, 0;
-       nop;
+       rted    r0, full_exception
+       addik   r5, r1, PTO              /* parameter struct pt_regs * regs */
 
 /*
  * Unaligned data trap.
@@ -584,19 +570,29 @@ C_ENTRY(full_exception_trap):
  * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
  */
 C_ENTRY(unaligned_data_trap):
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+       /* MS: I have to save r11 value and then restore it because
+        * set_bit, clear_eip, set_ee use r11 as temp register if MSR
+        * instructions are not used. We don't need to do if MSR instructions
+        * are used and they use r0 instead of r11.
+        * I am using ENTRY_SP which should be primary used only for stack
+        * pointer saving. */
+       swi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+       set_bip;        /* equalize initial state for all possible entries */
+       clear_eip;
+       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 */
-       la      r15, r0, ret_from_exc-8
+       addik   r15, r0, ret_from_exc-8
        mfs     r3, resr                /* ESR */
        nop
        mfs     r4, rear                /* EAR */
        nop
-       la      r7, r1, PTO             /* parameter struct pt_regs * regs */
-       la      r12, r0, _unaligned_data_exception
-       set_vms;
-       rtbd    r12, 0; /* interrupts enabled */
-       nop;
+       rtbd    r0, _unaligned_data_exception
+       addik   r7, r1, PTO             /* parameter struct pt_regs * regs */
 
 /*
  * Page fault traps.
@@ -617,38 +613,35 @@ C_ENTRY(unaligned_data_trap):
  */
 /* data and intruction trap - which is choose is resolved int fault.c */
 C_ENTRY(page_fault_data_trap):
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
        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 */
-       la      r15, r0, ret_from_exc-8
-       la      r5, r1, PTO             /* parameter struct pt_regs * regs */
+       addik   r15, r0, ret_from_exc-8
        mfs     r6, rear                /* parameter unsigned long address */
        nop
        mfs     r7, resr                /* parameter unsigned long error_code */
        nop
-       la      r12, r0, do_page_fault
-       set_vms;
-       rtbd    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):
-       swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
        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 */
-       la      r15, r0, ret_from_exc-8
-       la      r5, r1, PTO             /* parameter struct pt_regs * regs */
+       addik   r15, r0, ret_from_exc-8
        mfs     r6, rear                /* parameter unsigned long address */
        nop
        ori     r7, r0, 0               /* parameter unsigned long error_code */
-       la      r12, r0, do_page_fault
-       set_vms;
-       rtbd    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):
-       set_bip;                        /*  Ints masked for state restore*/
-       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.  */
 
@@ -680,13 +673,13 @@ C_ENTRY(ret_from_exc):
         * 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. */
-       la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
+       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     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
+1:     set_bip;                        /* Ints masked for state restore */
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
        VM_OFF;
        tophys(r1,r1);
@@ -697,7 +690,8 @@ C_ENTRY(ret_from_exc):
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
        bri     6f;
 /* Return to kernel state.  */
-2:     VM_OFF;
+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.  */
@@ -722,32 +716,25 @@ 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. */
-       lwi     r11, r0, TOPHYS(PER_CPU(KM));
-       beqi    r11, 1f; /* MS: Jump ahead if coming from user */
+       mfs     r1, rmsr
+       nop
+       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 */
+       swi     r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
        brid    2f;
        nop; /* MS: Fill delay slot */
 
 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);
@@ -761,18 +748,13 @@ C_ENTRY(_interrupt):
        swi     r0, r1, PTO + PT_MODE;
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1;
-       /* setup kernel mode to KM */
-       addi    r11, r0, 1;
-       swi     r11, r0, TOPHYS(PER_CPU(KM));
-
 2:
        lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
-       swi     r0, r1, PTO + PT_R0;
        tovirt(r1,r1)
-       la      r5, r1, PTO;
+       addik   r5, r1, PTO;
        set_vms;
-       la      r11, r0, do_IRQ;
-       la      r15, r0, irq_call;
+       addik   r11, r0, do_IRQ;
+       addik   r15, r0, irq_call;
 irq_call:rtbd  r11, 0;
        nop;
 
@@ -795,7 +777,7 @@ ret_from_irq:
        beqid   r11, no_intr_resched
 /* Handle a signal return; Pending signals should be in r18. */
        addi    r7, r0, 0; /* Arg 3: int in_syscall */
-       la      r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
+       addik   r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
        bralid  r15, do_signal; /* Handle any signals */
        add     r6, r0, r0; /* Arg 2: sigset_t *oldset */
 
@@ -803,7 +785,6 @@ ret_from_irq:
 no_intr_resched:
     /* Disable interrupts, we are now committed to the state restore */
        disable_irq
-       swi     r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
        VM_OFF;
        tophys(r1,r1);
@@ -854,27 +835,21 @@ 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;
-       lwi     r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
-       beqi    r11, 1f;                /* Jump ahead if coming from user */
+       mfs     r1, rmsr
+       nop
+       andi    r1, r1, MSR_UMS
+       bnei    r1, 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 */
+       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+       tophys(r1,r1);
 
        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;
+       swi     r1, 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 */
@@ -884,28 +859,21 @@ 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     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.  */
-       addi    r11, r0, 1;
-       swi     r11, r0, TOPHYS(PER_CPU(KM));   /* Now we're in kernel-mode.  */
-2:     lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
-       /* Save away the syscall number.  */
-       swi     r0, r1, PTO+PT_R0;
+2:
        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 */
-
-       set_vms;
-       la      r11, r0, send_sig;
-       la      r15, r0, dbtrap_call;
-dbtrap_call:   rtbd    r11, 0;
-       nop;
+dbtrap_call:   rtbd    r0, send_sig;
+       addik   r15, r0, dbtrap_call;
 
        set_bip;                        /*  Ints masked for state restore*/
-       lwi     r11, r1, PTO+PT_MODE;
+       lwi     r11, r1, PTO + PT_MODE;
        bnei    r11, 2f;
 
        /* Get current task ptr into r11 */
@@ -937,14 +905,14 @@ dbtrap_call:      rtbd    r11, 0;
           the normal entry sequence, so that it may be safely restored
           (in a possibly modified form) after do_signal returns.  */
 
-       la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
+       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     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
+1:
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
        VM_OFF;
        tophys(r1,r1);