Subversion Repositories HelenOS

Rev

Rev 2277 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2277 Rev 2278
Line 32... Line 32...
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <arch/mm/page.h>
35
#include <arch/mm/page.h>
36
#include <genarch/mm/page_pt.h>
36
#include <genarch/mm/page_pt.h>
37
#include <arch.h>
-
 
38
#include <mm/page.h>
37
#include <mm/page.h>
39
#include <align.h>
38
#include <align.h>
40
#include <config.h>
39
#include <config.h>
41
#include <arch/exception.h>
40
#include <arch/exception.h>
42
#include <typedefs.h>
41
#include <typedefs.h>
43
#include <arch/types.h>
42
#include <arch/types.h>
44
#include <interrupt.h>
43
#include <interrupt.h>
45
#include <arch/debug_print/print.h>
44
#include <arch/debug_print/print.h>
46
 
45
 
47
 
46
 
48
// localy used types
-
 
49
/**
-
 
50
 * Decribes structure of fault status register in coprocessor 15
-
 
51
 */
-
 
52
typedef struct {
-
 
53
        unsigned status              : 3;
-
 
54
        unsigned domain              : 4;
-
 
55
        unsigned zero            : 1;
-
 
56
        unsigned should_be_zero      : 24;
-
 
57
} __attribute__ ((packed)) fault_status_t;
-
 
58
 
-
 
59
/**
-
 
60
 * Help union used for overcasting integer value into fault_status_t type
-
 
61
 */
-
 
62
typedef union {
-
 
63
    fault_status_t  fsr;
-
 
64
    uint32_t    dummy;
-
 
65
} fault_status_union_t;
-
 
66
 
-
 
67
/**
-
 
68
 * Very simplyfied description of instruction code structure intended for
-
 
69
 * recognising memmory access of instruction ( reads or writes into memmory)
-
 
70
 * more details: see ARM architecture preference chapter:3.1 Instruction set encoding
-
 
71
 */
-
 
72
typedef struct {
-
 
73
        unsigned dummy1              : 4;
-
 
74
        unsigned bit4                : 1;
-
 
75
        unsigned bits567             : 3;
-
 
76
        unsigned dummy               : 12;
-
 
77
        unsigned access              : 1;
-
 
78
        unsigned opcode              : 4;
-
 
79
        unsigned instr_type          : 3;
-
 
80
        unsigned condition       : 4;
-
 
81
} __attribute__ ((packed)) instruction_t;
-
 
82
 
-
 
83
/**
-
 
84
 *  Help union used for overcasting ip register (uint_32_t) value into instruction_t pointer
-
 
85
 */
-
 
86
typedef union {
-
 
87
    instruction_t*  instr;
-
 
88
    uint32_t    ip;
-
 
89
} instruction_union_t;
-
 
90
 
-
 
91
// localy used functions
-
 
92
static fault_status_t read_fault_status_register();
-
 
93
static uintptr_t read_fault_address_register();
-
 
94
static pf_access_t get_memmory_access_type(uint32_t instr_addr, uintptr_t badvaddr);
-
 
95
 
-
 
96
 
-
 
97
/**
47
/**
98
 * Initializes kernel adress space page tables, sets abourts exceptions vectors
48
 * Initializes kernel adress space page tables, sets abourts exceptions vectors
99
 */
49
 */
100
void page_arch_init(void)
50
void page_arch_init(void)
101
{
51
{
Line 155... Line 105...
155
    last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
105
    last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
156
 
106
 
157
    return virtaddr;
107
    return virtaddr;
158
}
108
}
159
 
109
 
160
//TODO: remove in final version
-
 
161
static void print_istate(istate_t* istate);
-
 
162
static void print_istate(istate_t* istate) {
-
 
163
 dprintf("\nIstate dump:\n");
-
 
164
 dprintf("    r0:%X    r1:%X    r2:%X    r3:%X\n", istate->r0,  istate->r1, istate->r2,  istate->r3);
-
 
165
 dprintf("    r4:%X    r5:%X    r6:%X    r7:%X\n", istate->r4,  istate->r5, istate->r6,  istate->r7);
-
 
166
 dprintf("    r8:%X    r8:%X   r10:%X   r11:%X\n", istate->r8,  istate->r9, istate->r10, istate->r11);
-
 
167
 dprintf("   r12:%X    sp:%X    lr:%X  spsr:%X\n", istate->r12, istate->sp, istate->lr,  istate->spsr);
-
 
168
}
-
 
169
 
-
 
170
/**
-
 
171
 * \return Value stored in fault status register
-
 
172
 */
-
 
173
static fault_status_t read_fault_status_register() {
-
 
174
        fault_status_union_t tmp;
-
 
175
        asm volatile (
-
 
176
        "mrc p15, 0, %0, c5, c0, 0"
-
 
177
            : "=r"(tmp.dummy)
-
 
178
    );
-
 
179
    return tmp.fsr;
-
 
180
}
-
 
181
 
-
 
182
/**
-
 
183
 * \return Virtual adress. Access on this addres caused exception
-
 
184
 */
-
 
185
static uintptr_t read_fault_address_register() {
-
 
186
        uintptr_t tmp;
-
 
187
    // Fault adress is stored in coprocessor15, register 6
-
 
188
    asm volatile (
-
 
189
        "mrc p15, 0, %0, c6, c0, 0"
-
 
190
        : "=r"(tmp)
-
 
191
    );
-
 
192
    return tmp;
-
 
193
};
-
 
194
 
-
 
195
/**
-
 
196
 * Decode instruction and decide if try to read or write into memmory.
-
 
197
 *
-
 
198
 * \param instr_addr address of instruction which attempts to access into memmory
-
 
199
 * \param badvaddr Virtual address on which instruction tries to access
-
 
200
 * \return type of access into memmory
-
 
201
 *  Note: return PF_ACESS_EXEC if no memmory acess
-
 
202
 */
-
 
203
//TODO: remove debug print in final version ... instead panic return PF_ACESS_EXEC
-
 
204
pf_access_t get_memmory_access_type(uint32_t instr_addr, uintptr_t badvaddr) {
-
 
205
        instruction_union_t tmp;
-
 
206
        tmp.ip = instr_addr;
-
 
207
    // get instruction op code
-
 
208
    instruction_t i_code = *(tmp.instr);
-
 
209
 
-
 
210
        dprintf("get_instruction_memmory_access\n");
-
 
211
    dprintf(" i_code:%X\n",i_code);
-
 
212
    dprintf(" i_code.condition:%d\n", i_code.condition);
-
 
213
    dprintf(" i_code.instr_type:%d\n",i_code.instr_type);
-
 
214
    dprintf(" i_code.opcode:%d\n",i_code.opcode);
-
 
215
    dprintf(" i_code.acess:%d\n", i_code.access);
-
 
216
    dprintf(" i_code.dummy:%d\n", i_code.dummy);
-
 
217
    dprintf(" i_code.bits567%d\n", i_code.bits567);
-
 
218
    dprintf(" i_code.bit4:%d\n", i_code.bit4);
-
 
219
    dprintf(" i_code.dummy1:%d\n", i_code.dummy1);
-
 
220
 
-
 
221
 
-
 
222
        // undefined instructions ... (or special instructions)
-
 
223
    if ( i_code.condition == 0xf ) {
-
 
224
        panic("page_fault - on instruction not acessing to memmory (instr_code:%X, badvaddr:%X)",i_code, badvaddr);
-
 
225
        return PF_ACCESS_EXEC;
-
 
226
    }
-
 
227
 
-
 
228
    // load store instructions
-
 
229
        if ( ( i_code.instr_type == 0x2 ) || // load store immediate offset
-
 
230
             ( i_code.instr_type == 0x3 && i_code.bit4 == 0) || // load store register offset
-
 
231
             ( i_code.instr_type == 0x4 ) || // load store multiple
-
 
232
         ( i_code.instr_type == 0x6 )    // coprocessor load / strore
-
 
233
       ) {
-
 
234
        if ( i_code.access == 1) {
-
 
235
            return PF_ACCESS_READ;
-
 
236
        } else {
-
 
237
            return PF_ACCESS_WRITE;
-
 
238
        }
-
 
239
    };
-
 
240
 
-
 
241
    // swap, swpb instruction
-
 
242
    if ( i_code.instr_type == 0x0 && (i_code.opcode == 0x8 || i_code.opcode == 0xA) &&
-
 
243
         i_code.access == 0x0 && i_code.bits567 == 0x4 && i_code.bit4 == 1 )
-
 
244
     {
-
 
245
        /* Swap instructions make read and write in one step.
-
 
246
         * Type of access that caused exception have to page tables and access rights.
-
 
247
         */
-
 
248
//TODO: ALF!!!!! cann't use AS as is define as THE->as and THE structure is sored after stack_base of current thread
-
 
249
//      but now ... in exception we have separate stacks <==> different stack_pointer ... so AS contains nonsence data
-
 
250
//  same case as_page_fault .... it's nessesary to solve "stack" problem
-
 
251
                pte_level1_t* pte = (pte_level1_t*)pt_mapping_operations.mapping_find(AS, badvaddr);
-
 
252
 
-
 
253
        ASSERT(pte);
-
 
254
 
-
 
255
                /* check if read possible
-
 
256
                 * Note: Don't check PTE_READABLE because it returns 1 everytimes */
-
 
257
        if ( !PTE_PRESENT(pte) ) {
-
 
258
                return PF_ACCESS_READ;
-
 
259
        }
-
 
260
        if ( !PTE_WRITABLE(pte) ) {
-
 
261
            return PF_ACCESS_WRITE;
-
 
262
        }
-
 
263
        else
-
 
264
            // badvaddr is present readable and writeable but error occured ... why?
-
 
265
            panic("page_fault - swap instruction, but address readable and writeable (instr_code:%X, badvaddr:%X)",i_code, badvaddr);
-
 
266
    }
-
 
267
    panic("page_fault - on instruction not acessing to memmory (instr_code:%X, badvaddr:%X)",i_code, badvaddr);
-
 
268
    return PF_ACCESS_EXEC;
-
 
269
}
-
 
270
 
-
 
271
/**
-
 
272
 * Routine that solves exception data_abourt
-
 
273
 *  ... you try to load or store value into invalid memmory address
-
 
274
 * \param istate State of CPU when data abourt occured
-
 
275
 * \param n number of exception
-
 
276
 */
-
 
277
//TODO: remove debug prints in final tested version
-
 
278
void data_abort(int n, istate_t *istate) {
-
 
279
        fault_status_t fsr = read_fault_status_register();
-
 
280
        uintptr_t  page = read_fault_address_register();
-
 
281
 
-
 
282
    pf_access_t access = get_memmory_access_type( istate->lr, page);
-
 
283
 
-
 
284
    print_istate(istate);
-
 
285
    dprintf(" page fault : ip:%X, va:%X, status:%x(%x), access:%d\n", istate->lr, page, fsr.status,fsr, access);
-
 
286
 
-
 
287
/* Alf: Will be commented until stack problem will be solved ...
-
 
288
    as_page_fault make consequent page faults
-
 
289
 
-
 
290
        int ret = as_page_fault(page, access, istate);
-
 
291
    dprintf(" as_page_fault ret:%d\n", ret);
-
 
292
        if (ret == AS_PF_FAULT) {
-
 
293
        fault_if_from_uspace(istate, "Page fault: %#x", page);
-
 
294
 
-
 
295
                panic("page fault\n");
-
 
296
        }
-
 
297
*/
-
 
298
    // TODO: Remove this ... now for testing purposes ... it's bad to test page faults in kernel, where no page faults should occures
-
 
299
    panic("page fault ... solved\n");
-
 
300
 
-
 
301
}
-
 
302
 
-
 
303
/**
-
 
304
 * Routine that solves exception prefetch_about
-
 
305
 *  ... you try to execute instruction on invalid address
-
 
306
 * \param istate State of CPU when prefetch abourt occured
-
 
307
 * \param n number of exception
-
 
308
 */
-
 
309
void prefetch_abort(int n, istate_t *istate) {
-
 
310
 // Prefetch can be made be bkpt instruction
-
 
311
    print_istate(istate);
-
 
312
    dprintf(" prefetch_abourt ... instruction on adress:%x can't be fetched\n", istate->lr);
-
 
313
 
-
 
314
/* Alf: Will be commented until stack problem will be solved ...
-
 
315
    as_page_fault make consequent page faults
-
 
316
 
-
 
317
    int ret = as_page_fault(istate->lr, PF_ACCESS_EXEC, istate);
-
 
318
    dprintf(" as_page_fault ret:%d\n", ret);
-
 
319
        if (ret == AS_PF_FAULT) {
-
 
320
                panic("page fault - instruction fetch at addr:%X\n", istate->lr);
-
 
321
        }
-
 
322
*/
-
 
323
 
-
 
324
    panic("Prefetch abourt ... solved");
-
 
325
}
-
 
326
 
110
 
327
/** @}
111
/** @}
328
 */
112
 */
329
 
113