1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/errno.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/mm.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/user.h>
25#include <linux/interrupt.h>
26
27#include <asm/pgtable.h>
28#include <asm/uaccess.h>
29#include <asm/io.h>
30
31
32
33#define LFS 48
34#define LFD 50
35#define LFDU 51
36#define STFD 54
37#define STFDU 55
38#define FMR 63
39
40void print_8xx_pte(struct mm_struct *mm, unsigned long addr)
41{
42 pgd_t *pgd;
43 pmd_t *pmd;
44 pte_t *pte;
45
46 printk(" pte @ 0x%8lx: ", addr);
47 pgd = pgd_offset(mm, addr & PAGE_MASK);
48 if (pgd) {
49 pmd = pmd_offset(pud_offset(pgd, addr & PAGE_MASK),
50 addr & PAGE_MASK);
51 if (pmd && pmd_present(*pmd)) {
52 pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
53 if (pte) {
54 printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
55 (long)pgd, (long)pte, (long)pte_val(*pte));
56#define pp ((long)pte_val(*pte))
57 printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
58 "CI: %lx v: %lx\n",
59 pp>>12,
60 (pp>>10)&3,
61 (pp>>3)&1,
62 (pp>>2)&1,
63 (pp>>1)&1,
64 pp&1
65 );
66#undef pp
67 }
68 else {
69 printk("no pte\n");
70 }
71 }
72 else {
73 printk("no pmd\n");
74 }
75 }
76 else {
77 printk("no pgd\n");
78 }
79}
80
81int get_8xx_pte(struct mm_struct *mm, unsigned long addr)
82{
83 pgd_t *pgd;
84 pmd_t *pmd;
85 pte_t *pte;
86 int retval = 0;
87
88 pgd = pgd_offset(mm, addr & PAGE_MASK);
89 if (pgd) {
90 pmd = pmd_offset(pud_offset(pgd, addr & PAGE_MASK),
91 addr & PAGE_MASK);
92 if (pmd && pmd_present(*pmd)) {
93 pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
94 if (pte) {
95 retval = (int)pte_val(*pte);
96 }
97 }
98 }
99 return retval;
100}
101
102
103
104
105
106int Soft_emulate_8xx(struct pt_regs *regs)
107{
108 u32 inst, instword;
109 u32 flreg, idxreg, disp;
110 int retval;
111 s16 sdisp;
112 u32 *ea, *ip;
113
114 retval = 0;
115
116 instword = *((u32 *)regs->nip);
117 inst = instword >> 26;
118
119 flreg = (instword >> 21) & 0x1f;
120 idxreg = (instword >> 16) & 0x1f;
121 disp = instword & 0xffff;
122
123 ea = (u32 *)(regs->gpr[idxreg] + disp);
124 ip = (u32 *)¤t->thread.TS_FPR(flreg);
125
126 switch ( inst )
127 {
128 case LFD:
129
130
131
132 sdisp = (instword & 0xffff);
133 ea = (u32 *)(regs->gpr[idxreg] + sdisp);
134 if (copy_from_user(ip, ea, sizeof(double)))
135 retval = -EFAULT;
136 break;
137
138 case LFDU:
139 if (copy_from_user(ip, ea, sizeof(double)))
140 retval = -EFAULT;
141 else
142 regs->gpr[idxreg] = (u32)ea;
143 break;
144 case LFS:
145 sdisp = (instword & 0xffff);
146 ea = (u32 *)(regs->gpr[idxreg] + sdisp);
147 if (copy_from_user(ip, ea, sizeof(float)))
148 retval = -EFAULT;
149 break;
150 case STFD:
151
152
153
154 sdisp = (instword & 0xffff);
155 ea = (u32 *)(regs->gpr[idxreg] + sdisp);
156 if (copy_to_user(ea, ip, sizeof(double)))
157 retval = -EFAULT;
158 break;
159
160 case STFDU:
161 if (copy_to_user(ea, ip, sizeof(double)))
162 retval = -EFAULT;
163 else
164 regs->gpr[idxreg] = (u32)ea;
165 break;
166 case FMR:
167
168 memcpy(ip, ¤t->thread.TS_FPR((instword>>11)&0x1f),
169 sizeof(double));
170 break;
171 default:
172 retval = 1;
173 printk("Bad emulation %s/%d\n"
174 " NIP: %08lx instruction: %08x opcode: %x "
175 "A: %x B: %x C: %x code: %x rc: %x\n",
176 current->comm,current->pid,
177 regs->nip,
178 instword,inst,
179 (instword>>16)&0x1f,
180 (instword>>11)&0x1f,
181 (instword>>6)&0x1f,
182 (instword>>1)&0x3ff,
183 instword&1);
184 {
185 int pa;
186 print_8xx_pte(current->mm,regs->nip);
187 pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
188 pa |= (regs->nip & ~PAGE_MASK);
189 pa = (unsigned long)__va(pa);
190 printk("Kernel VA for NIP %x ", pa);
191 print_8xx_pte(current->mm,pa);
192 }
193 }
194
195 if (retval == 0)
196 regs->nip += 4;
197
198 return retval;
199}
200