Subversion Repositories HelenOS

Rev

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

Rev 2410 Rev 2415
Line 41... Line 41...
41
#include <arch.h>
41
#include <arch.h>
42
#include <interrupt.h>
42
#include <interrupt.h>
43
 
43
 
44
 
44
 
45
/** Returns value stored in fault status register.
45
/** Returns value stored in fault status register.
46
 *      FSR contain reason of page fault
-
 
47
 *
46
 *
48
 *  @return Value stored in CP15 fault status register (FSR).
47
 *  @return Value stored in CP15 fault status register (FSR).
49
 */
48
 */
50
static inline fault_status_t read_fault_status_register(void)
49
static inline fault_status_t read_fault_status_register(void)
51
{
50
{
52
    fault_status_union_t fsu;
51
    fault_status_union_t fsu;
53
 
52
 
54
    // fault adress is stored in CP15 register 5
53
    // fault status is stored in CP15 register 5
55
    asm volatile (
54
    asm volatile (
56
        "mrc p15, 0, %0, c5, c0, 0"
55
        "mrc p15, 0, %0, c5, c0, 0"
57
        : "=r"(fsu.dummy)
56
        : "=r"(fsu.dummy)
58
    );
57
    );
59
    return fsu.fs;
58
    return fsu.fs;
Line 75... Line 74...
75
    );
74
    );
76
    return ret;
75
    return ret;
77
}
76
}
78
 
77
 
79
 
78
 
80
/** Decides whether the instructions is load/store or not.
79
/** Decides whether the instruction is load/store or not.
81
 *
80
 *
82
 * @param instr Instruction
81
 * @param instr Instruction
83
 *
82
 *
84
 * @return true when instruction is load/store, false otherwise
83
 * @return true when instruction is load/store, false otherwise
85
 */
84
 */
Line 128... Line 127...
128
}
127
}
129
 
128
 
130
 
129
 
131
/** Decides whether read or write into memory is requested.
130
/** Decides whether read or write into memory is requested.
132
 *
131
 *
133
 * @param instr_addr   Address of instruction which tries to access memory
132
 * @param instr_addr   Address of instruction which tries to access memory.
134
 * @param badvaddr     Virtual address the instruction tries to access
133
 * @param badvaddr     Virtual address the instruction tries to access.
135
 *
134
 *
136
 * @return Type of access into memmory
-
 
137
 * Note:   Returns #PF_ACCESS_EXEC if no memory access is requested
135
 * @return Type of access into memmory, #PF_ACCESS_EXEC if no memory access is requested.
138
 */
136
 */
139
static pf_access_t get_memory_access_type(uint32_t instr_addr, uintptr_t badvaddr)
137
static pf_access_t get_memory_access_type(uint32_t instr_addr, uintptr_t badvaddr)
140
{  
138
{  
141
    instruction_union_t instr_union;
139
    instruction_union_t instr_union;
142
    instr_union.pc = instr_addr;
140
    instr_union.pc = instr_addr;
143
 
141
 
144
    instruction_t instr = *(instr_union.instr);
142
    instruction_t instr = *(instr_union.instr);
145
 
143
 
146
    // undefined instructions
144
    // undefined instructions
147
    if (instr.condition == 0xf) {
145
    if (instr.condition == 0xf) {
148
        panic("page_fault - instruction not access memmory (instr_code: %x, badvaddr:%x)",
146
        panic("page_fault - instruction doesn't access memory (instr_code: %x, badvaddr:%x)",
149
            instr, badvaddr);
147
            instr, badvaddr);
150
        return PF_ACCESS_EXEC;
148
        return PF_ACCESS_EXEC;
151
    }
149
    }
152
 
150
 
153
    // load store instructions
151
    // load store instructions
Line 159... Line 157...
159
        }
157
        }
160
    }
158
    }
161
 
159
 
162
    // swap, swpb instruction
160
    // swap, swpb instruction
163
    if (is_swap_instruction(instr)) {
161
    if (is_swap_instruction(instr)) {
164
        /* Swap instructions make read and write in one step.
-
 
165
         * Type of access that caused exception have to page tables
-
 
166
         *  and access rights.
-
 
167
         */
-
 
168
       
-
 
169
        pte_level1_t* pte = (pte_level1_t*)
-
 
170
        pt_mapping_operations.mapping_find(AS, badvaddr);
-
 
171
 
-
 
172
        if ( pte == NULL ) {
-
 
173
            return PF_ACCESS_READ;
-
 
174
        }
-
 
175
 
-
 
176
        /* check if read possible
-
 
177
        * Note: Don't check PTE_READABLE because it returns 1 everytimes */
-
 
178
        if ( !PTE_PRESENT(pte) ) {
-
 
179
            return PF_ACCESS_READ;
-
 
180
        }
-
 
181
 
-
 
182
        if ( !PTE_WRITABLE(pte) ) {
-
 
183
            return PF_ACCESS_WRITE;
162
        return PF_ACCESS_WRITE;
184
        } else {
-
 
185
            // badvaddr is present readable and writeable but error occured ... why?
-
 
186
            panic("page_fault - swap instruction, but address readable and writeable"
-
 
187
                "(instr_code:%X, badvaddr:%X)", instr, badvaddr);
-
 
188
        }
-
 
189
    }
163
    }
190
 
164
 
191
    panic("page_fault - instruction not access memory (instr_code: %x, badvaddr:%x)",
165
    panic("page_fault - instruction doesn't access memory (instr_code: %x, badvaddr:%x)",
192
        instr, badvaddr);
166
        instr, badvaddr);
193
 
167
 
194
    return PF_ACCESS_EXEC;
168
    return PF_ACCESS_EXEC;
195
}
169
}
196
 
170
 
197
/** Handles "data abort" exception (load or store at invalid address).
171
/** Handles "data abort" exception (load or store at invalid address).
198
 *
172
 *
199
 * @param exc_no    exception number
173
 * @param exc_no    Exception number.
200
 * @param istate    CPU state when exception occured
174
 * @param istate    CPU state when exception occured.
201
 */
175
 */
202
void data_abort(int exc_no, istate_t *istate)
176
void data_abort(int exc_no, istate_t *istate)
203
{
177
{
204
    fault_status_t fsr = read_fault_status_register();
178
    fault_status_t fsr = read_fault_status_register();
205
    uintptr_t badvaddr = read_fault_address_register();
179
    uintptr_t badvaddr = read_fault_address_register();
Line 218... Line 192...
218
    }
192
    }
219
}
193
}
220
 
194
 
221
/** Handles "prefetch abort" exception (instruction couldn't be executed).
195
/** Handles "prefetch abort" exception (instruction couldn't be executed).
222
 *
196
 *
223
 * @param exc_no    exception number
197
 * @param exc_no    Exception number.
224
 * @param istate    CPU state when exception occured
198
 * @param istate    CPU state when exception occured.
225
 */
199
 */
226
void prefetch_abort(int exc_no, istate_t *istate)
200
void prefetch_abort(int exc_no, istate_t *istate)
227
{
201
{
228
    int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
202
    int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
229
 
203