POK(kernelpart)
|
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 }