Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/cris/arch-v10/mm/fault.c
15125 views
1
/*
2
* linux/arch/cris/mm/fault.c
3
*
4
* Low level bus fault handler
5
*
6
*
7
* Copyright (C) 2000-2007 Axis Communications AB
8
*
9
* Authors: Bjorn Wesen
10
*
11
*/
12
13
#include <linux/mm.h>
14
#include <asm/uaccess.h>
15
#include <asm/pgtable.h>
16
#include <arch/svinto.h>
17
#include <asm/mmu_context.h>
18
19
/* debug of low-level TLB reload */
20
#undef DEBUG
21
22
#ifdef DEBUG
23
#define D(x) x
24
#else
25
#define D(x)
26
#endif
27
28
extern const struct exception_table_entry
29
*search_exception_tables(unsigned long addr);
30
31
asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs,
32
int protection, int writeaccess);
33
34
/* fast TLB-fill fault handler
35
* this is called from entry.S with interrupts disabled
36
*/
37
38
void
39
handle_mmu_bus_fault(struct pt_regs *regs)
40
{
41
int cause;
42
int select;
43
#ifdef DEBUG
44
int index;
45
int page_id;
46
int acc, inv;
47
#endif
48
pgd_t* pgd = (pgd_t*)per_cpu(current_pgd, smp_processor_id());
49
pmd_t *pmd;
50
pte_t pte;
51
int miss, we, writeac;
52
unsigned long address;
53
unsigned long flags;
54
55
cause = *R_MMU_CAUSE;
56
57
address = cause & PAGE_MASK; /* get faulting address */
58
select = *R_TLB_SELECT;
59
60
#ifdef DEBUG
61
page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause);
62
acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause);
63
inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause);
64
index = IO_EXTRACT(R_TLB_SELECT, index, select);
65
#endif
66
miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause);
67
we = IO_EXTRACT(R_MMU_CAUSE, we_excp, cause);
68
writeac = IO_EXTRACT(R_MMU_CAUSE, wr_rd, cause);
69
70
D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n",
71
regs->irp, address, miss, inv, we, acc, index, page_id));
72
73
/* leave it to the MM system fault handler */
74
if (miss)
75
do_page_fault(address, regs, 0, writeac);
76
else
77
do_page_fault(address, regs, 1, we);
78
79
/* Reload TLB with new entry to avoid an extra miss exception.
80
* do_page_fault may have flushed the TLB so we have to restore
81
* the MMU registers.
82
*/
83
local_irq_save(flags);
84
pmd = (pmd_t *)(pgd + pgd_index(address));
85
if (pmd_none(*pmd))
86
goto exit;
87
pte = *pte_offset_kernel(pmd, address);
88
if (!pte_present(pte))
89
goto exit;
90
*R_TLB_SELECT = select;
91
*R_TLB_HI = cause;
92
*R_TLB_LO = pte_val(pte);
93
exit:
94
local_irq_restore(flags);
95
}
96
97