Subversion Repositories HelenOS

Rev

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

Rev 3386 Rev 4153
Line 32... Line 32...
32
/** @file
32
/** @file
33
 *  @brief Page fault related functions.
33
 *  @brief Page fault related functions.
34
 */
34
 */
35
#include <panic.h>
35
#include <panic.h>
36
#include <arch/exception.h>
36
#include <arch/exception.h>
37
#include <arch/debug/print.h>
-
 
38
#include <arch/mm/page_fault.h>
37
#include <arch/mm/page_fault.h>
39
#include <mm/as.h>
38
#include <mm/as.h>
40
#include <genarch/mm/page_pt.h>
39
#include <genarch/mm/page_pt.h>
41
#include <arch.h>
40
#include <arch.h>
42
#include <interrupt.h>
41
#include <interrupt.h>
Line 50... Line 49...
50
{
49
{
51
    fault_status_union_t fsu;
50
    fault_status_union_t fsu;
52
 
51
   
53
    /* fault status is stored in CP15 register 5 */
52
    /* fault status is stored in CP15 register 5 */
54
    asm volatile (
53
    asm volatile (
55
        "mrc p15, 0, %0, c5, c0, 0"
54
        "mrc p15, 0, %[dummy], c5, c0, 0"
56
        : "=r"(fsu.dummy)
55
        : [dummy] "=r" (fsu.dummy)
57
    );
56
    );
-
 
57
   
58
    return fsu.fs;
58
    return fsu.fs;
59
}
59
}
60
 
60
 
61
/** Returns FAR (fault address register) content.
61
/** Returns FAR (fault address register) content.
62
 *
62
 *
Line 67... Line 67...
67
{
67
{
68
    uintptr_t ret;
68
    uintptr_t ret;
69
 
69
   
70
    /* fault adress is stored in CP15 register 6 */
70
    /* fault adress is stored in CP15 register 6 */
71
    asm volatile (
71
    asm volatile (
72
        "mrc p15, 0, %0, c6, c0, 0"
72
        "mrc p15, 0, %[ret], c6, c0, 0"
73
        : "=r"(ret)
73
        : [ret] "=r" (ret)
74
    );
74
    );
-
 
75
   
75
    return ret;
76
    return ret;
76
}
77
}
77
 
78
 
78
/** Decides whether the instruction is load/store or not.
79
/** Decides whether the instruction is load/store or not.
79
 *
80
 *
80
 * @param instr Instruction
81
 * @param instr Instruction
81
 *
82
 *
82
 * @return true when instruction is load/store, false otherwise
83
 * @return true when instruction is load/store, false otherwise
-
 
84
 *
83
 */
85
 */
84
static inline bool is_load_store_instruction(instruction_t instr)
86
static inline bool is_load_store_instruction(instruction_t instr)
85
{
87
{
86
    /* load store immediate offset */
88
    /* load store immediate offset */
87
    if (instr.type == 0x2) {
89
    if (instr.type == 0x2)
88
        return true;
90
        return true;
89
    }
-
 
90
 
91
   
91
    /* load store register offset */
92
    /* load store register offset */
92
    if (instr.type == 0x3 && instr.bit4 == 0) {
93
    if ((instr.type == 0x3) && (instr.bit4 == 0))
93
        return true;
94
        return true;
94
    }
-
 
95
 
95
   
96
    /* load store multiple */
96
    /* load store multiple */
97
    if (instr.type == 0x4) {
97
    if (instr.type == 0x4)
98
        return true;
98
        return true;
99
    }
-
 
100
 
99
   
101
    /* oprocessor load/store */
100
    /* oprocessor load/store */
102
    if (instr.type == 0x6) {
101
    if (instr.type == 0x6)
103
        return true;
102
        return true;
104
    }
-
 
105
 
103
   
106
    return false;
104
    return false;
107
}
105
}
108
 
106
 
109
/** Decides whether the instruction is swap or not.
107
/** Decides whether the instruction is swap or not.
Line 113... Line 111...
113
 * @return true when instruction is swap, false otherwise
111
 * @return true when instruction is swap, false otherwise
114
 */
112
 */
115
static inline bool is_swap_instruction(instruction_t instr)
113
static inline bool is_swap_instruction(instruction_t instr)
116
{
114
{
117
    /* swap, swapb instruction */
115
    /* swap, swapb instruction */
118
    if (instr.type == 0x0 &&
116
    if ((instr.type == 0x0) &&
119
        (instr.opcode == 0x8 || instr.opcode == 0xa) &&
117
        ((instr.opcode == 0x8) || (instr.opcode == 0xa)) &&
120
        instr.access == 0x0 && instr.bits567 == 0x4 && instr.bit4 == 1) {
118
        (instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1))
121
        return true;
119
        return true;
122
    }
-
 
123
 
120
   
124
    return false;
121
    return false;
125
}
122
}
126
 
123
 
127
/** Decides whether read or write into memory is requested.
124
/** Decides whether read or write into memory is requested.
Line 140... Line 137...
140
 
137
 
141
    instruction_t instr = *(instr_union.instr);
138
    instruction_t instr = *(instr_union.instr);
142
 
139
 
143
    /* undefined instructions */
140
    /* undefined instructions */
144
    if (instr.condition == 0xf) {
141
    if (instr.condition == 0xf) {
145
        panic("page_fault - instruction doesn't access memory "
142
        panic("page_fault - instruction does not access memory "
146
            "(instr_code: %x, badvaddr:%x)", instr, badvaddr);
143
            "(instr_code: %x, badvaddr:%x).", instr, badvaddr);
147
        return PF_ACCESS_EXEC;
144
        return PF_ACCESS_EXEC;
148
    }
145
    }
149
 
146
 
150
    /* load store instructions */
147
    /* load store instructions */
151
    if (is_load_store_instruction(instr)) {
148
    if (is_load_store_instruction(instr)) {
Line 160... Line 157...
160
    if (is_swap_instruction(instr)) {
157
    if (is_swap_instruction(instr)) {
161
        return PF_ACCESS_WRITE;
158
        return PF_ACCESS_WRITE;
162
    }
159
    }
163
 
160
 
164
    panic("page_fault - instruction doesn't access memory "
161
    panic("page_fault - instruction doesn't access memory "
165
        "(instr_code: %x, badvaddr:%x)", instr, badvaddr);
162
        "(instr_code: %x, badvaddr:%x).", instr, badvaddr);
166
 
163
 
167
    return PF_ACCESS_EXEC;
164
    return PF_ACCESS_EXEC;
168
}
165
}
169
 
166
 
170
/** Handles "data abort" exception (load or store at invalid address).
167
/** Handles "data abort" exception (load or store at invalid address).
Line 182... Line 179...
182
 
179
 
183
    int ret = as_page_fault(badvaddr, access, istate);
180
    int ret = as_page_fault(badvaddr, access, istate);
184
 
181
 
185
    if (ret == AS_PF_FAULT) {
182
    if (ret == AS_PF_FAULT) {
186
        print_istate(istate);
183
        print_istate(istate);
187
        dprintf("page fault - pc: %x, va: %x, status: %x(%x), "
184
        printf("page fault - pc: %x, va: %x, status: %x(%x), "
188
            "access:%d\n", istate->pc, badvaddr, fsr.status, fsr,
185
            "access:%d\n", istate->pc, badvaddr, fsr.status, fsr,
189
            access);
186
            access);
190
 
187
       
191
        fault_if_from_uspace(istate, "Page fault: %#x", badvaddr);
188
        fault_if_from_uspace(istate, "Page fault: %#x.", badvaddr);
192
        panic("page fault\n");
189
        panic("Page fault.");
193
    }
190
    }
194
}
191
}
195
 
192
 
196
/** Handles "prefetch abort" exception (instruction couldn't be executed).
193
/** Handles "prefetch abort" exception (instruction couldn't be executed).
197
 *
194
 *
Line 201... Line 198...
201
void prefetch_abort(int exc_no, istate_t *istate)
198
void prefetch_abort(int exc_no, istate_t *istate)
202
{
199
{
203
    int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
200
    int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
204
 
201
 
205
    if (ret == AS_PF_FAULT) {
202
    if (ret == AS_PF_FAULT) {
206
        dprintf("prefetch_abort\n");
203
        printf("prefetch_abort\n");
207
        print_istate(istate);
204
        print_istate(istate);
208
        panic("page fault - prefetch_abort at address: %x\n",
205
        panic("page fault - prefetch_abort at address: %x.",
209
            istate->pc);
206
            istate->pc);
210
    }
207
    }
211
}
208
}
212
 
209
 
213
/** @}
210
/** @}