diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index 0e609e9cade7a0b6134f4221a2358e4d1f3306b6..30afc542039cb56fd0d7e2addef998a4f2e09ae5 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -62,6 +62,11 @@ extern void halt(void) __attribute__((noreturn)); #define __halt() __asm__ __volatile__ ("sys_call %0 #halt" : : "i" (HMC_halt)) +#define fpu_enable() \ +{ \ + __asm__ __volatile__("sys_call %0" : : "i" (HMC_wrfen));\ +} + #define imb() \ __asm__ __volatile__ ("sys_call %0 #imb" : : "i" (HMC_imb) : "memory") diff --git a/arch/sw_64/include/asm/mmu_context.h b/arch/sw_64/include/asm/mmu_context.h index 762ffbf72dbb89bad42438ab734fe79487d509ff..3e75f34895bfa70ba4c6d36387d42083957c14dd 100644 --- a/arch/sw_64/include/asm/mmu_context.h +++ b/arch/sw_64/include/asm/mmu_context.h @@ -14,37 +14,14 @@ /* * Force a context reload. This is needed when we change the page - * table pointer or when we update the ASN of the current process. + * table pointer or when we update the ASID of the current process. + * + * CSR:UPN holds ASID and CSR:PTBR holds page table pointer. */ - -static inline unsigned long -__reload_thread(struct pcb_struct *pcb) -{ - register unsigned long a0 __asm__("$16"); - register unsigned long v0 __asm__("$0"); - - a0 = virt_to_phys(pcb); - __asm__ __volatile__( - "sys_call %2 #__reload_thread" - : "=r"(v0), "=r"(a0) - : "i"(HMC_swpctx), "r"(a0) - : "$1", "$22", "$23", "$24", "$25"); - - return v0; -} - #define load_asn_ptbr load_mm /* - * The maximum ASN's the processor supports. - * - * If a processor implements address space numbers (ASNs), and the old - * PTE has the Address Space Match (ASM) bit clear (ASNs in use) and - * the Valid bit set, then entries can also effectively be made coherent - * by assigning a new, unused ASN to the currently running process and - * not reusing the previous ASN before calling the appropriate HMcode - * routine to invalidate the translation buffer (TB). - * + * The maximum ASN's the processor supports. ASN is called ASID too. */ #ifdef CONFIG_SUBARCH_C3B diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index e43499d18357536e972a250780de9dfa1c11a709..4b2db3891dcb619455e1674b8d0c442702e4defc 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -76,17 +76,14 @@ __smp_callin: sys_call HMC_whami # Get hard cid - sll $0, 2, $0 ldi $1, __rcid_to_cpu - addl $1, $0, $1 + s4addl $0, $1, $1 ldw $0, 0($1) # Get logical cpu number - sll $0, 3, $0 - ldi $1, tidle_pcb - addl $1, $0, $1 - ldl $16, 0($1) # Get PCBB of idle thread + ldi $2, tidle_ksp + s8addl $0, $2, $2 + ldl $30, 0($2) # Get ksp of idle thread - sys_call HMC_swpctx ldi $8, 0x3fff # Find "current". bic $30, $8, $8 diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 4d223a7255bbf2579c7059000ef3edbb29a4767e..f5525a194072fdd690ecbee16b8adfff7eb6f5e5 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -156,7 +156,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, struct pt_regs *childregs = task_pt_regs(p); struct pt_regs *regs = current_pt_regs(); - childti->pcb.ksp = (unsigned long) childregs; childti->pcb.flags = 7; /* set FEN, clear everything else */ p->thread.sp = (unsigned long) childregs; diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index b95873a2696dda39dcaf0aa2da23974fc7070d19..43d803c49545620417428a5fa3ba0d2fc72118cc 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -34,7 +34,7 @@ EXPORT_SYMBOL(__cpu_to_rcid); int __rcid_to_cpu[NR_CPUS]; /* Map physical to logical */ EXPORT_SYMBOL(__rcid_to_cpu); -unsigned long tidle_pcb[NR_CPUS]; +void *tidle_ksp[NR_CPUS]; /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; @@ -110,6 +110,8 @@ void smp_callin(void) /* All kernel threads share the same mm context. */ mmgrab(&init_mm); current->active_mm = &init_mm; + /* update csr:ptbr */ + wrptbr(PFN_PHYS(current_thread_info()->pcb.ptbr)); /* inform the notifiers about the new cpu */ notify_cpu_starting(cpuid); @@ -153,23 +155,11 @@ static inline void set_secondary_ready(int cpuid) */ static int secondary_cpu_start(int cpuid, struct task_struct *idle) { - struct pcb_struct *ipcb; unsigned long timeout; - - ipcb = &task_thread_info(idle)->pcb; - /* - * Initialize the idle's PCB to something just good enough for - * us to get started. Immediately after starting, we'll swpctx - * to the target idle task's pcb. Reuse the stack in the mean - * time. Precalculate the target PCBB. + * Precalculate the target ksp. */ - ipcb->ksp = (unsigned long)ipcb + sizeof(union thread_union) - 16; - ipcb->usp = 0; - ipcb->pcc = 0; - ipcb->asn = 0; - tidle_pcb[cpuid] = ipcb->unique = virt_to_phys(ipcb); - ipcb->dv_match = ipcb->dv_mask = 0; + tidle_ksp[cpuid] = idle->stack + sizeof(union thread_union) - 16; DBGS("Starting secondary cpu %d: state 0x%lx\n", cpuid, idle->state); diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 9915160d95d2da442ce9f65c82ed95d6822963d3..ff32330d73abd0220c9d1cdd5e667713e57cb373 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -284,7 +284,7 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) * with it. */ current_thread_info()->pcb.flags |= 1; - __reload_thread(¤t_thread_info()->pcb); + fpu_enable(); return; case 5: /* illoc */ diff --git a/arch/sw_64/mm/fault.c b/arch/sw_64/mm/fault.c index 541e30b4b84ccbcdf234e3e853d928ef1b50b5f8..b7fc2c81669872dbc042afc373af12ecbbc16a99 100644 --- a/arch/sw_64/mm/fault.c +++ b/arch/sw_64/mm/fault.c @@ -76,7 +76,7 @@ void __load_new_mm_context(struct mm_struct *next_mm) pcb->asn = mmc & HARDWARE_ASN_MASK; pcb->ptbr = virt_to_pfn(next_mm->pgd); - __reload_thread(pcb); + load_asn_ptbr(pcb->asn, pcb->ptbr); } /* diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 6ed1ef8e020cfb19e15468b8ebf4e573cf601dd8..ef8e45ece0ff4860c8603c648f862d28e97a9a8c 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -77,21 +77,12 @@ pgd_alloc(struct mm_struct *mm) return ret; } -static inline unsigned long -load_PCB(struct pcb_struct *pcb) -{ - register unsigned long sp __asm__("$30"); - pcb->ksp = sp; - return __reload_thread(pcb); -} - /* Set up initial PCB, VPTB, and other such nicities. */ static inline void switch_to_system_map(void) { unsigned long newptbr; - unsigned long original_pcb_ptr; /* * Initialize the kernel's page tables. Linux puts the vptb in @@ -103,7 +94,7 @@ switch_to_system_map(void) /* Also set up the real kernel PCB while we're at it. */ init_thread_info.pcb.ptbr = newptbr; init_thread_info.pcb.flags = 1; /* set FEN, clear everything else */ - original_pcb_ptr = load_PCB(&init_thread_info.pcb); + wrptbr(PFN_PHYS(newptbr)); tbiv(); }