mirror of
https://github.com/gwenhael-le-moine/x49gp.git
synced 2024-12-27 21:58:33 +01:00
192 lines
5.3 KiB
Diff
192 lines
5.3 KiB
Diff
diff -ur qemu-0.9.0/target-arm/helper.c qemu/target-arm/helper.c
|
|
--- qemu-0.9.0/target-arm/helper.c 2007-07-30 16:48:18.000000000 +0200
|
|
+++ qemu/target-arm/helper.c 2007-07-30 16:46:50.000000000 +0200
|
|
@@ -278,87 +280,101 @@
|
|
static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
|
|
int is_user, uint32_t *phys_ptr, int *prot)
|
|
{
|
|
- int code;
|
|
- uint32_t table;
|
|
- uint32_t desc;
|
|
- int type;
|
|
- int ap;
|
|
- int domain;
|
|
- uint32_t phys_addr;
|
|
+ int code;
|
|
+ uint32_t pgdp, ptep;
|
|
+ uint32_t pgd, pte = 0;
|
|
+ uint32_t index;
|
|
+ int ap = 0;
|
|
+ int domain = 0;
|
|
+ uint32_t phys_addr = 0;
|
|
+
|
|
+ /* Fast Context Switch Extension. */
|
|
+ if (address < 0x02000000)
|
|
+ address += env->cp15.c13_fcse;
|
|
+
|
|
+ if ((env->cp15.c1_sys & 1) == 0) {
|
|
+ /* MMU disabled. */
|
|
+ *phys_ptr = address;
|
|
+ *prot = PAGE_READ | PAGE_WRITE;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* Pagetable walk. */
|
|
+
|
|
+ /* Lookup l1 descriptor. */
|
|
+ pgdp = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
|
|
+
|
|
+ pgd = ldl_phys(pgdp);
|
|
+
|
|
+ switch (pgd & 3) {
|
|
+ case 0: /* Section translation fault. */
|
|
+ code = 5;
|
|
+ goto do_fault;
|
|
+
|
|
+ case 1: /* Coarse page table. */
|
|
+ index = (address >> 10) & 0x3fc;
|
|
+ ptep = (pgd & 0xfffffc00) | index;
|
|
+
|
|
+ pte = ldl_phys(ptep);
|
|
+ break;
|
|
+
|
|
+ case 2: /* Section. */
|
|
+ phys_addr = (pgd & 0xfff00000) | (address & 0x000fffff);
|
|
+
|
|
+ domain = (pgd >> 5) & 0x0f;
|
|
+ ap = (pgd >> 10) & 0x03;
|
|
+ code = 13;
|
|
+
|
|
+ goto do_check;
|
|
+
|
|
+ case 3: /* Fine page table. */
|
|
+ index = (address >> 8) & 0xffc;
|
|
+ ptep = (pgd & 0xfffff000) | index;
|
|
+
|
|
+ pte = ldl_phys(ptep);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ code = 15;
|
|
+ switch (pte & 3) {
|
|
+ case 0: /* Page translation fault. */
|
|
+ code = 7;
|
|
+ goto do_fault;
|
|
+
|
|
+ case 1: /* Large page. */
|
|
+ phys_addr = (pte & 0xffff0000) | (address & 0x0000ffff);
|
|
+
|
|
+ domain = (pgd >> 5) & 0x0f;
|
|
+ ap = (pte >> (4 + ((address >> 13) & 6))) & 3;
|
|
+ break;
|
|
+
|
|
+ case 2: /* Small page. */
|
|
+ phys_addr = (pte & 0xfffff000) | (address & 0x00000fff);
|
|
+
|
|
+ domain = (pgd >> 5) & 0x0f;
|
|
+ ap = (pte >> (4 + ((address >> 13) & 6))) & 3;
|
|
+ break;
|
|
+
|
|
+ case 3: /* Tiny page. */
|
|
+ phys_addr = (pte & 0xfffffc00) | (address & 0x000003ff);
|
|
+
|
|
+ domain = (pgd >> 5) & 0x0f;
|
|
+ ap = (pte >> 4) & 3;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+do_check:
|
|
+ *prot = check_ap(env, ap, domain, access_type, is_user);
|
|
+ if (!*prot) {
|
|
+ /* Access permission fault. */
|
|
+ goto do_fault;
|
|
+ }
|
|
|
|
- /* Fast Context Switch Extension. */
|
|
- if (address < 0x02000000)
|
|
- address += env->cp15.c13_fcse;
|
|
-
|
|
- if ((env->cp15.c1_sys & 1) == 0) {
|
|
- /* MMU diusabled. */
|
|
- *phys_ptr = address;
|
|
- *prot = PAGE_READ | PAGE_WRITE;
|
|
- } else {
|
|
- /* Pagetable walk. */
|
|
- /* Lookup l1 descriptor. */
|
|
- table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
|
|
- desc = ldl_phys(table);
|
|
- type = (desc & 3);
|
|
- domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
|
|
- if (type == 0) {
|
|
- /* Secton translation fault. */
|
|
- code = 5;
|
|
- goto do_fault;
|
|
- }
|
|
- if (domain == 0 || domain == 2) {
|
|
- if (type == 2)
|
|
- code = 9; /* Section domain fault. */
|
|
- else
|
|
- code = 11; /* Page domain fault. */
|
|
- goto do_fault;
|
|
- }
|
|
- if (type == 2) {
|
|
- /* 1Mb section. */
|
|
- phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
|
|
- ap = (desc >> 10) & 3;
|
|
- code = 13;
|
|
- } else {
|
|
- /* Lookup l2 entry. */
|
|
- table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
|
|
- desc = ldl_phys(table);
|
|
- switch (desc & 3) {
|
|
- case 0: /* Page translation fault. */
|
|
- code = 7;
|
|
- goto do_fault;
|
|
- case 1: /* 64k page. */
|
|
- phys_addr = (desc & 0xffff0000) | (address & 0xffff);
|
|
- ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
|
|
- break;
|
|
- case 2: /* 4k page. */
|
|
- phys_addr = (desc & 0xfffff000) | (address & 0xfff);
|
|
- ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
|
|
- break;
|
|
- case 3: /* 1k page. */
|
|
- if (type == 1) {
|
|
- /* Page translation fault. */
|
|
- code = 7;
|
|
- goto do_fault;
|
|
- }
|
|
- phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
|
|
- ap = (desc >> 4) & 3;
|
|
- break;
|
|
- default:
|
|
- /* Never happens, but compiler isn't smart enough to tell. */
|
|
- abort();
|
|
- }
|
|
- code = 15;
|
|
- }
|
|
- *prot = check_ap(env, ap, domain, access_type, is_user);
|
|
- if (!*prot) {
|
|
- /* Access permission fault. */
|
|
- goto do_fault;
|
|
- }
|
|
*phys_ptr = phys_addr;
|
|
- }
|
|
- return 0;
|
|
+ return 0;
|
|
+
|
|
do_fault:
|
|
- return code | (domain << 4);
|
|
+ return code | (domain << 4);
|
|
}
|
|
|
|
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
|
|
@@ -532,7 +548,7 @@
|
|
return;
|
|
bad_reg:
|
|
/* ??? For debugging only. Should raise illegal instruction exception. */
|
|
- cpu_abort(env, "Unimplemented cp15 register read\n");
|
|
+ cpu_abort(env, "Unimplemented cp15 register write\n");
|
|
}
|
|
|
|
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
|