x49gp/qemu/patches/qemu-0.9.0-x49gp-arm-mmu.patch

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)