Linux on PowerPC 学习笔记(1)

1. 准备:

1.1. 资料收集

freescale的网站上下载下面的几个pdf文件:

名称

内容

EREFRM.pdf

A Programmer's Reference Manual for Freescale Embedded Processors

E500CORERM.pdf

PowerPC™ e500 Core Family Reference Manual

E500ABIUG.pdf

PowerPC™ e500 Application Binary Interface User's Guide

MPC5554.pdf

MPC5554 Microcontroller Data Sheet

MPC5553_MPC5554_RM.pdf

MPC5553/5554 Microcontroller Reference Manual

1.2. Linux源代码下载:

http://www.kernel.org/

2. CPU学习

2.1. 寄存器

E500内核寄存器分为用户模式(ULR)和特权模式(SLR):

 Linux on PowerPC 学习笔记(1)_第1张图片

Linux on PowerPC 学习笔记(1)_第2张图片

它们的访问受MSRMachine State Register)的PR位的控制,PR=0时可以访问SLR。而MSR只有处于特权模式下才能访问,因此只有通过中断、系统调用和异常才能实现用户态到特权态的切换。

MSR寄存器如下所示:

linux-2.6.33\arch\powerpc\include\asm\reg_booke.h中可以看到,Linux如下定义MSR的各个位:

/* Machine State Register (MSR) Fields */ 

#define MSR_SF_LG    63 /* Enable 64 bit mode */ 

#define MSR_ISF_LG    61 /* Interrupt 64b mode valid on 630 */ 

#define MSR_HV_LG     60 /* Hypervisor state */ 

#define MSR_VEC_LG    25     /* Enable AltiVec */ 

#define MSR_VSX_LG    23        /* Enable VSX */ 

#define MSR_POW_LG    18        /* Enable Power Management */ 

#define MSR_WE_LG    18        /* Wait State Enable */ 

#define MSR_TGPR_LG    17        /* TLB Update registers in use */ 

#define MSR_CE_LG    17        /* Critical Interrupt Enable */ 

#define MSR_ILE_LG    16        /* Interrupt Little Endian */ 

#define MSR_EE_LG    15        /* External Interrupt Enable */ 

#define MSR_PR_LG    14        /* Problem State / Privilege Level */ 

#define MSR_FP_LG    13        /* Floating Point enable */ 

#define MSR_ME_LG    12        /* Machine Check Enable */ 

#define MSR_FE0_LG    11        /* Floating Exception mode 0 */ 

#define MSR_SE_LG    10        /* Single Step */ 

#define MSR_BE_LG    9        /* Branch Trace */ 

#define MSR_DE_LG    9         /* Debug Exception Enable */ 

#define MSR_FE1_LG    8        /* Floating Exception mode 1 */ 

#define MSR_IP_LG    6        /* Exception prefix 0x000/0xFFF */ 

#define MSR_IR_LG    5         /* Instruction Relocate */ 

#define MSR_DR_LG    4         /* Data Relocate */ 

#define MSR_PE_LG    3        /* Protection Enable */ 

#define MSR_PX_LG    2        /* Protection Exclusive Mode */ 

#define MSR_PMM_LG    2        /* Performance monitor */ 

#define MSR_RI_LG    1        /* Recoverable Exception */ 

#define MSR_LE_LG    0         /* Little Endian */ 

 

#define MSR_GS        (1<<28) /* Guest state */ 

#define MSR_UCLE    (1<<26)    /* User-mode cache lock enable */ 

#define MSR_SPE        (1<<25)    /* Enable SPE */ 

#define MSR_DWE        (1<<10)    /* Debug Wait Enable */ 

#define MSR_UBLE    (1<<10)    /* BTB lock enable (e500) */ 

#define MSR_IS        MSR_IR    /* Instruction Space */ 

#define MSR_DS        MSR_DR    /* Data Space */ 

#define MSR_PMM        (1<<2)    /* Performance monitor mark bit */ 

#define MSR_CM        (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */ 

 

#if defined(CONFIG_PPC_BOOK3E_64) 

#define MSR_        MSR_ME | MSR_CE 

#define MSR_KERNEL MSR_ | MSR_CM 

#define MSR_USER32    MSR_ | MSR_PR | MSR_EE 

#define MSR_USER64    MSR_USER32 | MSR_CM 

#elif defined (CONFIG_40x) 

#define MSR_KERNEL    (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE) 

#define MSR_USER    (MSR_KERNEL|MSR_PR|MSR_EE) 

#else 

#define MSR_KERNEL    (MSR_ME|MSR_RI|MSR_CE) 

#define MSR_USER    (MSR_KERNEL|MSR_PR|MSR_EE) 

#endif 

从上面红色内容可以看出,Linux内核态和用户态MSR的区别。

Linux进程启动函数(execve)中,需要从系统态到用户态转换这个转换函数在start_thread()中完成,如下:

void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) 

{ 

    set_fs(USER_DS); 

 

    /* 

     * If we exec out of a kernel thread then thread.regs will not be 

     * set. Do it now. 

     */ 

    if (!current->thread.regs) { 

        struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE; 

        current->thread.regs = regs - 1; 

    } 

 

    memset(regs->gpr, 0, sizeof(regs->gpr)); 

    regs->ctr = 0; 

    regs->link = 0; 

    regs->xer = 0; 

    regs->ccr = 0; 

    regs->gpr[1] = sp; 

 

    /* 

     * We have just cleared all the nonvolatile GPRs, so make 

     * FULL_REGS(regs) return true. This is necessary to allow 

     * ptrace to examine the thread immediately after exec. 

     */ 

    regs->trap &= ~1UL; 

    regs->mq = 0; 

    regs->nip = start; 

    regs->msr = MSR_USER; 

    discard_lazy_cpu_state(); 

#ifdef CONFIG_VSX 

    current->thread.used_vsr = 0; 

#endif    memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); 

    current->thread.fpscr.val = 0; 

#ifdef CONFIG_ALTIVEC 

    memset(current->thread.vr, 0, sizeof(current->thread.vr)); 

    memset(&current->thread.vscr, 0, sizeof(current->thread.vscr)); 

    current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ 

    current->thread.vrsave = 0; 

    current->thread.used_vr = 0; 

#endif /* CONFIG_ALTIVEC */ 

#ifdef CONFIG_SPE 

    memset(current->thread.evr, 0, sizeof(current->thread.evr)); 

    current->thread.acc = 0; 

    current->thread.spefscr = 0; 

    current->thread.used_spe = 0; 

#endif /* CONFIG_SPE */ 

} 

你可能感兴趣的:(linux)