/*
* Alpha emulation - PALcode emulation for qemu.
- *
+ *
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
};
#if 0
-/* One must explicitely check that the TB is valid and the FOE bit is reset */
-static void update_itb ()
+/* One must explicitly check that the TB is valid and the FOE bit is reset */
+static void update_itb (void)
{
/* This writes into a temp register, not the actual one */
mtpr(TB_TAG);
mtpr(TB_CTL);
/* This commits the TB update */
- mtpr(ITB_PTE);
+ mtpr(ITB_PTE);
}
-static void update_dtb ();
+static void update_dtb (void);
{
mtpr(TB_CTL);
/* This write into a temp register, not the actual one */
static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
uint64_t ptebase, int page_bits, uint64_t level,
- int is_user, int rw)
+ int mmu_idx, int rw)
{
uint64_t pteaddr, pte, pfn;
uint8_t gh;
- int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar;
+ int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
+ /* XXX: TOFIX */
+ is_user = mmu_idx == MMU_USER_IDX;
pteaddr = (ptebase << page_bits) + (8 * level);
pte = ldq_raw(pteaddr);
/* Decode all interresting PTE fields */
static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
uint64_t ptebase, int page_bits,
- uint64_t vaddr, int is_user, int rw)
+ uint64_t vaddr, int mmu_idx, int rw)
{
uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
int lvl_bits, ret;
break;
}
/* Level 3 PTE */
- ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
+ ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
if (ret & 0x1) {
/* Translation not valid */
ret = 1;
}
}
*paddr = (pfn << page_bits) | (vaddr & page_mask);
-
+
return 0;
}
static int virtual_to_physical (CPUState *env, uint64_t *physp,
int *zbitsp, int *protp,
- uint64_t virtual, int is_user, int rw)
+ uint64_t virtual, int mmu_idx, int rw)
{
uint64_t sva, ptebase;
int seg, page_bits, ret;
case 0:
/* seg1: 3 levels of PTE */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
case 1:
/* seg1: 2 levels of PTE */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
case 2:
/* kernel segment */
- if (is_user) {
+ if (mmu_idx != 0) {
ret = 2;
} else {
*physp = virtual;
case 3:
/* seg1: TB mapped */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
default:
ret = 1;
/* XXX: code provision */
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
- int is_user, int is_softmmu)
+ int mmu_idx, int is_softmmu)
{
uint64_t physical, page_size, end;
int prot, zbits, ret;
- if (env->user_mode_only) {
+#if defined(CONFIG_USER_ONLY)
ret = 2;
- } else {
+#else
ret = virtual_to_physical(env, &physical, &zbits, &prot,
- address, is_user, rw);
- }
+ address, mmu_idx, rw);
+#endif
switch (ret) {
case 0:
/* No fault */
address &= ~(page_size - 1);
for (end = physical + page_size; physical < end; physical += 0x1000) {
ret = tlb_set_page(env, address, physical, prot,
- is_user, is_softmmu);
+ mmu_idx, is_softmmu);
address += 0x1000;
}
break;
void call_pal (CPUState *env, int palcode)
{
- target_ulong ret;
+ target_long ret;
- printf("%s: palcode %02x\n", __func__, palcode);
- if (logfile != NULL)
- fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
+ qemu_log("%s: palcode %02x\n", __func__, palcode);
switch (palcode) {
case 0x83:
/* CALLSYS */
- printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
- if (logfile != NULL)
- fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+ qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
env->ir[IR_A5]);
- env->ir[IR_A3] = ret;
- if (ret > (target_ulong)(-515)) {
- env->ir[IR_V0] = 1;
+ if (ret >= 0) {
+ env->ir[IR_A3] = 0;
+ env->ir[IR_V0] = ret;
} else {
- env->ir[IR_V0] = 0;
+ env->ir[IR_A3] = 1;
+ env->ir[IR_V0] = -ret;
}
break;
case 0x9E:
/* RDUNIQUE */
env->ir[IR_V0] = env->unique;
- printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+ qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
break;
case 0x9F:
/* WRUNIQUE */
env->unique = env->ir[IR_A0];
- printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+ qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
break;
default:
- printf("%s: unhandled palcode %02x\n", __func__, palcode);
- if (logfile != NULL)
- fprintf(logfile, "%s: unhandled palcode %02x\n",
+ qemu_log("%s: unhandled palcode %02x\n",
__func__, palcode);
exit(1);
}