29 |
|
|
30 |
#define CPU(f) (current_cpu->hw.f) |
#define CPU(f) (current_cpu->hw.f) |
31 |
|
|
|
#define REAL_MODE_P (! ((current_cpu)->hw.state & STATE_PROTECTED_MODE)) |
|
|
|
|
32 |
static void |
static void |
33 |
translate_address (struct mmu_transaction *tobj) |
translate_address (struct mmu_transaction *tobj) |
34 |
{ |
{ |
35 |
struct processor *current_cpu = tobj->cpu; |
struct processor *current_cpu = tobj->cpu; |
36 |
ADDR address = tobj->logical_addr; |
ADDR address = tobj->logical_addr; |
37 |
USI pde, pte; |
USI pde, pte; |
38 |
int is_dirty; |
int is_dirty, errcode = 0; |
39 |
CORE_ADDR pdep, ptep; |
CORE_ADDR pdep, ptep; |
40 |
|
|
41 |
if ((current_cpu->hw.hw_cr[0] & 0x80000000) == 0) |
if ((current_cpu->hw.hw_cr[0] & 0x80000000) == 0) |
47 |
|
|
48 |
pdep = (CPU (pgdir) + ((address >> 20) & ~3)); |
pdep = (CPU (pgdir) + ((address >> 20) & ~3)); |
49 |
pde = T2HUSI (*(USI *) pdep); |
pde = T2HUSI (*(USI *) pdep); |
50 |
if (! (pde & 1)) |
if (! (pde & PA_P)) |
51 |
goto do_fault; |
goto do_fault; |
52 |
if (tobj->supervisor_p == 0 && ! (pde & 4)) |
if (tobj->supervisor_p == 0 && !(pde & PA_US)) |
53 |
goto do_prot_fault; |
goto do_prot_fault; |
54 |
|
|
55 |
if ((pde & 0x100) && CPU (hw_cr[4]) & (1 << 4)) |
if ((pde & PA_PS) && CPU (hw_cr[4]) & (1 << 4)) |
56 |
{ |
{ |
57 |
is_dirty = (!tobj->read_p && (pde & (1 << 6))); |
is_dirty = (!tobj->read_p && (pde & (1 << 6))); |
58 |
if (! (pde & (1 << 5))) |
if ((pde & PA_P) == 0) |
59 |
{ |
{ |
60 |
pde |= (1 << 5); /* acccesed */ |
pde |= PA_P; |
61 |
if (is_dirty) |
if (is_dirty) |
62 |
pde |= (1 << 6); /* dirty */ |
pde |= PA_D; |
63 |
*(USI *) pdep = H2TUSI (pde); |
*(USI *) pdep = H2TUSI (pde); |
64 |
} |
} |
|
|
|
65 |
tobj->phys_addr = pde & ~0x003fffff; |
tobj->phys_addr = pde & ~0x003fffff; |
66 |
tobj->phys_addr |= (address & 0x003fffff); |
tobj->phys_addr |= (address & 0x003fffff); |
67 |
return; |
return; |
70 |
{ |
{ |
71 |
/* First update the PDE so we do not have to |
/* First update the PDE so we do not have to |
72 |
deal with it anymore. */ |
deal with it anymore. */ |
73 |
if (! (pde & (1 << 5))) |
if ((pde & PA_P) == 0) |
74 |
{ |
{ |
75 |
pde |= (1 << 5); /* accessed */ |
pde |= PA_P; |
76 |
*(USI *) pdep = H2TUSI (pde); |
*(USI *) pdep = H2TUSI (pde); |
77 |
} |
} |
78 |
|
|
80 |
pde & ~0xfff) |
pde & ~0xfff) |
81 |
+ ((address >> 10) & 0xffc)); |
+ ((address >> 10) & 0xffc)); |
82 |
pte = T2HUSI (*(USI *) ptep); |
pte = T2HUSI (*(USI *) ptep); |
83 |
if (! (pte & 1)) |
if (! (pte & PA_P)) |
84 |
goto do_fault; |
goto do_fault; |
85 |
if (tobj->supervisor_p) |
if (tobj->supervisor_p) |
86 |
{ |
{ |
106 |
|
|
107 |
tobj->phys_addr = pte & ~0xfff; |
tobj->phys_addr = pte & ~0xfff; |
108 |
tobj->phys_addr |= (address & 0xfff); |
tobj->phys_addr |= (address & 0xfff); |
|
|
|
|
#if 0 |
|
|
printf ("translated address %x into %x\n", |
|
|
address, tobj->phys_addr); |
|
|
#endif |
|
|
|
|
109 |
return; |
return; |
110 |
} |
} |
111 |
|
|
112 |
do_prot_fault: |
do_prot_fault: |
113 |
|
errcode = PF_ERROR_PROTECTION; |
114 |
do_fault: |
do_fault: |
115 |
ASSERT (0); |
CPU (hw_cr[2]) = address; |
116 |
|
|
117 |
|
if (tobj->read_p == 0) |
118 |
|
errcode |= PF_ERROR_WRITE; |
119 |
|
if (tobj->supervisor_p == 0) |
120 |
|
errcode |= PF_ERROR_USER; |
121 |
|
|
122 |
|
i386_raise_exception (current_cpu, EXC_PF, errcode, |
123 |
|
HW_PC_GET (current_cpu), 0); |
124 |
|
engine_restart (ENGINE_RESTART_VALUE); |
125 |
} |
} |
126 |
|
|
127 |
struct mmu_emulation i386_mmu = |
struct mmu_emulation i386_mmu = |