POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/arch/ppc/space.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by julien on Thu Jan 15 23:34:13 2009 
00015  */
00016 
00017 
00018 #include <types.h>
00019 #include <errno.h>
00020 #include <libc.h>
00021 #include <bsp.h>
00022 #include <core/sched.h>
00023 
00024 #include <arch.h>
00025 #include "thread.h"
00026 #include "msr.h"
00027 
00028 #define KERNEL_STACK_SIZE 8192
00029 
00030 #define PPC_SR_KP (1 << 29)
00031 #define PPC_SR_Ks (1 << 30)
00032 #define PPC_SR_T  (1 << 31)
00033 
00034 struct pok_space
00035 {
00036   uint32_t phys_base;
00037   uint32_t size;
00038 };
00039 
00040 struct pok_space spaces[POK_CONFIG_NB_PARTITIONS];
00041 
00042 pok_ret_t pok_create_space (uint8_t partition_id,
00043                             uint32_t addr,
00044                             uint32_t size)
00045 {
00046 #ifdef POK_NEEDS_DEBUG
00047   printf ("pok_create_space: %d: %x %x\n", partition_id, addr, size);
00048 #endif
00049   spaces[partition_id].phys_base = addr;
00050   spaces[partition_id].size = size;
00051 
00052   return (POK_ERRNO_OK);
00053 }
00054 
00055 pok_ret_t pok_space_switch (uint8_t old_partition_id,
00056                             uint8_t new_partition_id)
00057 {
00058   (void) old_partition_id;
00059   /* printf ("space_switch %u -> %u\n", old_partition_id, new_partition_id); */
00060   asm volatile ("mtsr %0,%1" : : "r"(0), "r"(PPC_SR_KP | new_partition_id));
00061   return (POK_ERRNO_OK);
00062 }
00063 
00064 uint32_t        pok_space_base_vaddr (uint32_t addr)
00065 {
00066    (void) addr;
00067    return (0);
00068 }
00069 
00070 extern void pok_arch_rfi (void);
00071 
00072 uint32_t        pok_space_context_create (uint8_t partition_id,
00073                                    uint32_t entry_rel,
00074                                    uint32_t stack_rel,
00075                                    uint32_t arg1,
00076                                    uint32_t arg2)
00077 {
00078   context_t* ctx;
00079   volatile_context_t* vctx;
00080   char*      stack_addr;
00081   (void) partition_id;
00082 
00083   stack_addr = pok_bsp_mem_alloc (KERNEL_STACK_SIZE);
00084 
00085   vctx = (volatile_context_t *)
00086     (stack_addr + KERNEL_STACK_SIZE - sizeof (volatile_context_t));
00087   ctx = (context_t *)((char *)vctx - sizeof (context_t) + 8);
00088 
00089   memset (ctx, 0, sizeof (*ctx));
00090   memset (vctx, 0, sizeof (*vctx));
00091 
00092   vctx->r3     = arg1;
00093   vctx->r4     = arg2;
00094   vctx->sp     = stack_rel - 12;
00095   vctx->srr0   = entry_rel;
00096   vctx->srr1   = MSR_EE | MSR_IP | MSR_DR | MSR_IR | MSR_PR;
00097   ctx->lr      = (uint32_t) pok_arch_rfi;
00098 
00099   ctx->sp      = (uint32_t) &vctx->sp;
00100 
00101 #ifdef POK_NEEDS_DEBUG
00102   printf ("space_context_create %d: entry=%x stack=%x arg1=%x arg2=%x ksp=%x\n",
00103           partition_id, entry_rel, stack_rel, arg1, arg2, &vctx->sp);
00104 #endif
00105 
00106   return (uint32_t)ctx;
00107 }
00108 
00109 typedef struct
00110 {
00111   uint32_t vsid_api;
00112   uint32_t rpn_flags;
00113 } ppc_pte_t;
00114 
00115 static uint32_t pt_base;
00116 static uint32_t pt_mask;
00117 
00118 #define PPC_PTE_V (1 << 31)
00119 #define POK_PAGE_SIZE (1 << 12)
00120 #define POK_PAGE_MASK (~(POK_PAGE_SIZE - 1))
00121 #define PPC_PTE_H (1 << 6)
00122 #define PPC_PTE_R (1 << 8)
00123 #define PPC_PTE_C (1 << 7)
00124 #define PPC_PTE_W (1 << 6)
00125 #define PPC_PTE_I (1 << 5)
00126 #define PPC_PTE_M (1 << 4)
00127 #define PPC_PTE_G (1 << 3)
00128 #define PPC_PTE_PP_NO 0
00129 #define PPC_PTE_PP_RO 1
00130 #define PPC_PTE_PP_RW 2
00131 
00132 void pok_arch_space_init (void)
00133 {
00134   uint32_t sdr1;
00135 
00136   pt_base = 0;
00137   pt_mask = 0x3ff;
00138 
00139   sdr1 = pt_base | (pt_mask >> 10);
00140   asm volatile ("mtsdr1 %0" : : "r"(sdr1));
00141 }
00142 
00143 static void pok_insert_pte (uint32_t vsid, uint32_t vaddr, uint32_t pte)
00144 {
00145   uint32_t hash = (vsid & 0x7ffff) ^ ((vaddr >> 12) & 0xffff);
00146   ppc_pte_t *pteg;
00147   int i;
00148 
00149   pteg = (ppc_pte_t *)(pt_base + ((hash & pt_mask) << 6));
00150   for (i = 0; i < 8; i++)
00151     if (!(pteg[i].vsid_api & PPC_PTE_V))
00152       {
00153         pteg[i].rpn_flags = pte;
00154         pteg[i].vsid_api = PPC_PTE_V | (vsid << 7) | ((vaddr >> 22) & 0x3f);
00155         return;
00156       }
00157 
00158   /* FIXME: Try secondary hash.  */
00159 
00160 #ifdef POK_NEEDS_DEBUG
00161   printf ("pok_insert_pte: no free entry\n");
00162 #endif
00163 
00164   while (1)
00165     ;
00166 }
00167 
00168 void pok_arch_isi_int (uint32_t pc, uint32_t msr)
00169 {
00170 
00171 #ifdef POK_NEEDS_DEBUG
00172   printf("isi_int: part=%d, pc=%x msr=%x\n",
00173          pok_current_partition, pc, msr);
00174 
00175   if (msr & ((1 << 28) | (1 << 27)))
00176   {
00177     printf (" Bad access\n");
00178   }
00179 #endif
00180 
00181   if (msr & (1 << 30))
00182     {
00183       /* Page fault  */
00184       if (pc < spaces[pok_current_partition].size)
00185         {
00186           uint32_t vaddr = pc & POK_PAGE_MASK;
00187           uint32_t v;
00188           v = (spaces[pok_current_partition].phys_base + vaddr) & POK_PAGE_MASK;
00189           v |= PPC_PTE_R | PPC_PTE_C | PPC_PTE_PP_RW;
00190           pok_insert_pte (pok_current_partition, vaddr, v);
00191           return;
00192         }
00193     }
00194 
00195 #ifdef POK_NEEDS_DEBUG
00196    printf("[DEBUG] Infinite loop in pok_arch_isi_int\n");
00197 #endif
00198 
00199   while (1)
00200     ;
00201 }
00202 
00203 void pok_arch_dsi_int (uint32_t dar, uint32_t dsisr)
00204 {
00205 #ifdef POK_NEEDS_DEBUG
00206   printf("dsi_int: part=%d, dar=%x dsisr=%x\n",
00207          pok_current_partition, dar, dsisr);
00208 #endif
00209 
00210   if (dsisr & (1 << 30))
00211     {
00212       /* Page fault  */
00213       if (dar < spaces[pok_current_partition].size)
00214         {
00215           uint32_t vaddr = dar & POK_PAGE_MASK;
00216           uint32_t v;
00217           v = (spaces[pok_current_partition].phys_base + vaddr) & POK_PAGE_MASK;
00218           v |= PPC_PTE_R | PPC_PTE_C | PPC_PTE_PP_RW;
00219           pok_insert_pte (pok_current_partition, vaddr, v);
00220           return;
00221         }
00222     }
00223 #ifdef POK_NEEDS_DEBUG
00224    printf("[DEBUG] Infinite loop in pok_arch_dsi_int\n");
00225 #endif
00226   while (1)
00227     ;
00228 }