target/hppa: Mask reserved PSW bits in expand_sm_imm
target/hppa: Fix calculation of CR_IIASQ back register target/hppa: Fix possible overflow in TLB size calculation target/hppa: Fix probe instruction target/hppa: Split MMU_PHYS_IDX to MMU_ABS_IDX, MMU_ABS_W_IDX target/hppa: Reduce TARGET_PHYS_ADDR_SPACE_BITS to 40 hw/pci-host/astro: Translate 32-bit pci onto 40-bit runway bus hw/hppa: Update SeaBIOS-hppa to version 12 -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmVSXR4dHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV87qwf+MkEuvMiwqx9YB2qa Yhn4m4H1DrQcqGJ2egGuiYrS45JCAUZUcXnmBxL//w3AW7hoeoZwmuFSj+I3EOhI y6ykMjMAe8d0VpWEvdkRh7SAWPBKvCJiAclkNyZkYhhagXryiFxqo9tL6nNQQEyz HaYzrDwqL+Qgh7/ahkA9XdVLdeTsMtXoLm1cCXpY+TL0MiQonBa1mc17vbyWN8hs qWQFBtik0lBIuEN0cB0bUgvV1oH9B8KVUYKbx/RhQORQAiU/O2SaSZ0fxU+F8ynB xIyQH6aik0pzgwSo25T/AMxxgUoDydvLDyLCu/R85eNmdgvOj+n4XGIiNEJKEltT 1OwGSQ== =Qcsh -----END PGP SIGNATURE----- Merge tag 'pull-pa-20231113' of https://gitlab.com/rth7680/qemu into staging target/hppa: Mask reserved PSW bits in expand_sm_imm target/hppa: Fix calculation of CR_IIASQ back register target/hppa: Fix possible overflow in TLB size calculation target/hppa: Fix probe instruction target/hppa: Split MMU_PHYS_IDX to MMU_ABS_IDX, MMU_ABS_W_IDX target/hppa: Reduce TARGET_PHYS_ADDR_SPACE_BITS to 40 hw/pci-host/astro: Translate 32-bit pci onto 40-bit runway bus hw/hppa: Update SeaBIOS-hppa to version 12 # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmVSXR4dHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV87qwf+MkEuvMiwqx9YB2qa # Yhn4m4H1DrQcqGJ2egGuiYrS45JCAUZUcXnmBxL//w3AW7hoeoZwmuFSj+I3EOhI # y6ykMjMAe8d0VpWEvdkRh7SAWPBKvCJiAclkNyZkYhhagXryiFxqo9tL6nNQQEyz # HaYzrDwqL+Qgh7/ahkA9XdVLdeTsMtXoLm1cCXpY+TL0MiQonBa1mc17vbyWN8hs # qWQFBtik0lBIuEN0cB0bUgvV1oH9B8KVUYKbx/RhQORQAiU/O2SaSZ0fxU+F8ynB # xIyQH6aik0pzgwSo25T/AMxxgUoDydvLDyLCu/R85eNmdgvOj+n4XGIiNEJKEltT # 1OwGSQ== # =Qcsh # -----END PGP SIGNATURE----- # gpg: Signature made Mon 13 Nov 2023 12:30:06 EST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-pa-20231113' of https://gitlab.com/rth7680/qemu: hw/hppa: Require at least SeaBIOS-hppa version 12 target/hppa: Update to SeaBIOS-hppa from version 10 to 12 hw/hppa: Move software power button address to page zero hw/pci-host/astro: Fix boot for C3700 machine target/hppa: Reduce TARGET_PHYS_ADDR_SPACE_BITS to 40 target/hppa: Replace MMU_PHYS_IDX with MMU_ABS_IDX, MMU_ABS_W_IDX target/hppa: Introduce MMU_IDX_MMU_DISABLED target/hppa: Fix possible overflow in TLB size calculation target/hppa: Fix calculation of CR_IIASQ back register target/hppa: Use PRIV_P_TO_MMU_IDX in helper_probe target/hppa: Use only low 2 immediate bits for PROBEI target/hppa: Mask reserved PSW bits in expand_sm_imm Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
315088134f
@ -34,9 +34,10 @@
|
|||||||
#include "net/net.h"
|
#include "net/net.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
|
||||||
#define MIN_SEABIOS_HPPA_VERSION 10 /* require at least this fw version */
|
#define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
|
||||||
|
|
||||||
#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
|
/* Power button address at &PAGE0->pad[4] */
|
||||||
|
#define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t))
|
||||||
|
|
||||||
#define enable_lasi_lan() 0
|
#define enable_lasi_lan() 0
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "hw/pci-host/astro.h"
|
#include "hw/pci-host/astro.h"
|
||||||
#include "hw/hppa/hppa_hardware.h"
|
#include "hw/hppa/hppa_hardware.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
|
#include "target/hppa/cpu.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
|
||||||
@ -268,22 +269,6 @@ static const MemoryRegionOps elroy_config_addr_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the
|
|
||||||
* given translated address and mask.
|
|
||||||
*/
|
|
||||||
static bool make_iommu_tlbe(hwaddr addr, hwaddr taddr, hwaddr mask,
|
|
||||||
IOMMUTLBEntry *ret)
|
|
||||||
{
|
|
||||||
hwaddr tce_mask = ~((1ull << 12) - 1);
|
|
||||||
ret->target_as = &address_space_memory;
|
|
||||||
ret->iova = addr & tce_mask;
|
|
||||||
ret->translated_addr = taddr & tce_mask;
|
|
||||||
ret->addr_mask = ~tce_mask;
|
|
||||||
ret->perm = IOMMU_RW;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle PCI-to-system address translation. */
|
/* Handle PCI-to-system address translation. */
|
||||||
static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
|
static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
|
||||||
hwaddr addr,
|
hwaddr addr,
|
||||||
@ -291,53 +276,59 @@ static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
|
|||||||
int iommu_idx)
|
int iommu_idx)
|
||||||
{
|
{
|
||||||
AstroState *s = container_of(iommu, AstroState, iommu);
|
AstroState *s = container_of(iommu, AstroState, iommu);
|
||||||
IOMMUTLBEntry ret = {
|
hwaddr pdir_ptr, index, ibase;
|
||||||
.target_as = &address_space_memory,
|
|
||||||
.iova = addr,
|
|
||||||
.translated_addr = 0,
|
|
||||||
.addr_mask = ~(hwaddr)0,
|
|
||||||
.perm = IOMMU_NONE,
|
|
||||||
};
|
|
||||||
hwaddr pdir_ptr, index, a, ibase;
|
|
||||||
hwaddr addr_mask = 0xfff; /* 4k translation */
|
hwaddr addr_mask = 0xfff; /* 4k translation */
|
||||||
uint64_t entry;
|
uint64_t entry;
|
||||||
|
|
||||||
#define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
|
#define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
|
||||||
#define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
|
#define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
|
||||||
#define IOVP_MASK PAGE_MASK
|
|
||||||
#define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
|
#define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
|
||||||
|
|
||||||
|
addr &= ~addr_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default translation: "32-bit PCI Addressing on 40-bit Runway".
|
||||||
|
* For addresses in the 32-bit memory address range ... and then
|
||||||
|
* language which not-coincidentally matches the PSW.W=0 mapping.
|
||||||
|
*/
|
||||||
|
if (addr <= UINT32_MAX) {
|
||||||
|
entry = hppa_abs_to_phys_pa2_w0(addr);
|
||||||
|
} else {
|
||||||
|
entry = addr;
|
||||||
|
}
|
||||||
|
|
||||||
/* "range enable" flag cleared? */
|
/* "range enable" flag cleared? */
|
||||||
if ((s->tlb_ibase & 1) == 0) {
|
if ((s->tlb_ibase & 1) == 0) {
|
||||||
make_iommu_tlbe(addr, addr, addr_mask, &ret);
|
goto skip;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a = addr;
|
|
||||||
ibase = s->tlb_ibase & ~1ULL;
|
ibase = s->tlb_ibase & ~1ULL;
|
||||||
if ((a & s->tlb_imask) != ibase) {
|
if ((addr & s->tlb_imask) != ibase) {
|
||||||
/* do not translate this one! */
|
/* do not translate this one! */
|
||||||
make_iommu_tlbe(addr, addr, addr_mask, &ret);
|
goto skip;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
index = PDIR_INDEX(a);
|
|
||||||
|
index = PDIR_INDEX(addr);
|
||||||
pdir_ptr = s->tlb_pdir_base + index * sizeof(entry);
|
pdir_ptr = s->tlb_pdir_base + index * sizeof(entry);
|
||||||
entry = ldq_le_phys(&address_space_memory, pdir_ptr);
|
entry = ldq_le_phys(&address_space_memory, pdir_ptr);
|
||||||
|
|
||||||
if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */
|
if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */
|
||||||
g_assert_not_reached();
|
/* failure */
|
||||||
goto failure;
|
return (IOMMUTLBEntry) { .perm = IOMMU_NONE };
|
||||||
}
|
}
|
||||||
|
|
||||||
entry &= ~SBA_PDIR_VALID_BIT;
|
entry &= ~SBA_PDIR_VALID_BIT;
|
||||||
entry >>= IOVP_SHIFT;
|
entry >>= IOVP_SHIFT;
|
||||||
entry <<= 12;
|
entry <<= 12;
|
||||||
entry |= addr & 0xfff;
|
|
||||||
make_iommu_tlbe(addr, entry, addr_mask, &ret);
|
|
||||||
goto success;
|
|
||||||
|
|
||||||
failure:
|
skip:
|
||||||
ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
|
return (IOMMUTLBEntry) {
|
||||||
success:
|
.target_as = &address_space_memory,
|
||||||
return ret;
|
.iova = addr,
|
||||||
|
.translated_addr = entry,
|
||||||
|
.addr_mask = addr_mask,
|
||||||
|
.perm = IOMMU_RW,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque,
|
static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque,
|
||||||
|
@ -29,7 +29,7 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
|
|||||||
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
|
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
|
||||||
|
|
||||||
# HPPA devices
|
# HPPA devices
|
||||||
pci_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c'))
|
specific_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c'))
|
||||||
pci_ss.add(when: 'CONFIG_DINO', if_true: files('dino.c'))
|
pci_ss.add(when: 'CONFIG_DINO', if_true: files('dino.c'))
|
||||||
|
|
||||||
system_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
|
system_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
|
||||||
|
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit fd5b6cf82369a1e53d68302fb6ede2b9e2afccd1
|
Subproject commit 2a23dd388fcc1068f9c4a3077e0662803743e1c8
|
@ -14,7 +14,8 @@
|
|||||||
# define TARGET_PHYS_ADDR_SPACE_BITS 32
|
# define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||||
# define TARGET_VIRT_ADDR_SPACE_BITS 32
|
# define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||||
#else
|
#else
|
||||||
# define TARGET_PHYS_ADDR_SPACE_BITS 64
|
/* ??? PA-8000 through 8600 have 40 bits; PA-8700 and 8900 have 44 bits. */
|
||||||
|
# define TARGET_PHYS_ADDR_SPACE_BITS 40
|
||||||
# define TARGET_VIRT_ADDR_SPACE_BITS 64
|
# define TARGET_VIRT_ADDR_SPACE_BITS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -31,23 +31,25 @@
|
|||||||
basis. It's probably easier to fall back to a strong memory model. */
|
basis. It's probably easier to fall back to a strong memory model. */
|
||||||
#define TCG_GUEST_DEFAULT_MO TCG_MO_ALL
|
#define TCG_GUEST_DEFAULT_MO TCG_MO_ALL
|
||||||
|
|
||||||
#define MMU_KERNEL_IDX 7
|
#define MMU_ABS_W_IDX 6
|
||||||
#define MMU_KERNEL_P_IDX 8
|
#define MMU_ABS_IDX 7
|
||||||
#define MMU_PL1_IDX 9
|
#define MMU_KERNEL_IDX 8
|
||||||
#define MMU_PL1_P_IDX 10
|
#define MMU_KERNEL_P_IDX 9
|
||||||
#define MMU_PL2_IDX 11
|
#define MMU_PL1_IDX 10
|
||||||
#define MMU_PL2_P_IDX 12
|
#define MMU_PL1_P_IDX 11
|
||||||
#define MMU_USER_IDX 13
|
#define MMU_PL2_IDX 12
|
||||||
#define MMU_USER_P_IDX 14
|
#define MMU_PL2_P_IDX 13
|
||||||
#define MMU_PHYS_IDX 15
|
#define MMU_USER_IDX 14
|
||||||
|
#define MMU_USER_P_IDX 15
|
||||||
|
|
||||||
|
#define MMU_IDX_MMU_DISABLED(MIDX) ((MIDX) < MMU_KERNEL_IDX)
|
||||||
#define MMU_IDX_TO_PRIV(MIDX) (((MIDX) - MMU_KERNEL_IDX) / 2)
|
#define MMU_IDX_TO_PRIV(MIDX) (((MIDX) - MMU_KERNEL_IDX) / 2)
|
||||||
#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
|
#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
|
||||||
#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
|
#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
|
||||||
|
|
||||||
#define TARGET_INSN_START_EXTRA_WORDS 2
|
#define TARGET_INSN_START_EXTRA_WORDS 2
|
||||||
|
|
||||||
/* No need to flush MMU_PHYS_IDX */
|
/* No need to flush MMU_ABS*_IDX */
|
||||||
#define HPPA_MMU_FLUSH_MASK \
|
#define HPPA_MMU_FLUSH_MASK \
|
||||||
(1 << MMU_KERNEL_IDX | 1 << MMU_KERNEL_P_IDX | \
|
(1 << MMU_KERNEL_IDX | 1 << MMU_KERNEL_P_IDX | \
|
||||||
1 << MMU_PL1_IDX | 1 << MMU_PL1_P_IDX | \
|
1 << MMU_PL1_IDX | 1 << MMU_PL1_P_IDX | \
|
||||||
@ -287,7 +289,8 @@ static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch)
|
|||||||
if (env->psw & (ifetch ? PSW_C : PSW_D)) {
|
if (env->psw & (ifetch ? PSW_C : PSW_D)) {
|
||||||
return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P);
|
return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P);
|
||||||
}
|
}
|
||||||
return MMU_PHYS_IDX; /* mmu disabled */
|
/* mmu disabled */
|
||||||
|
return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
|||||||
env->cr[CR_IIASQ] =
|
env->cr[CR_IIASQ] =
|
||||||
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
|
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
|
||||||
env->cr_back[0] =
|
env->cr_back[0] =
|
||||||
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
|
hppa_form_gva_psw(old_psw, env->iasq_b, env->iaoq_b) >> 32;
|
||||||
} else {
|
} else {
|
||||||
env->cr[CR_IIASQ] = 0;
|
env->cr[CR_IIASQ] = 0;
|
||||||
env->cr_back[0] = 0;
|
env->cr_back[0] = 0;
|
||||||
|
@ -27,41 +27,39 @@
|
|||||||
|
|
||||||
hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr)
|
hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr)
|
||||||
{
|
{
|
||||||
if (likely(extract64(addr, 58, 4) != 0xf)) {
|
/*
|
||||||
/* Memory address space */
|
* Figure H-8 "62-bit Absolute Accesses when PSW W-bit is 1" describes
|
||||||
return addr & MAKE_64BIT_MASK(0, 62);
|
* an algorithm in which a 62-bit absolute address is transformed to
|
||||||
}
|
* a 64-bit physical address. This must then be combined with that
|
||||||
if (extract64(addr, 54, 4) != 0) {
|
* pictured in Figure H-11 "Physical Address Space Mapping", in which
|
||||||
/* I/O address space */
|
* the full physical address is truncated to the N-bit physical address
|
||||||
return addr | MAKE_64BIT_MASK(62, 2);
|
* supported by the implementation.
|
||||||
}
|
*
|
||||||
/* PDC address space */
|
* Since the supported physical address space is below 54 bits, the
|
||||||
return (addr & MAKE_64BIT_MASK(0, 54)) | MAKE_64BIT_MASK(60, 4);
|
* H-8 algorithm is moot and all that is left is to truncate.
|
||||||
|
*/
|
||||||
|
QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > 54);
|
||||||
|
return sextract64(addr, 0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr)
|
hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* See Figure H-10, "Absolute Accesses when PSW W-bit is 0",
|
||||||
|
* combined with Figure H-11, as above.
|
||||||
|
*/
|
||||||
if (likely(extract32(addr, 28, 4) != 0xf)) {
|
if (likely(extract32(addr, 28, 4) != 0xf)) {
|
||||||
/* Memory address space */
|
/* Memory address space */
|
||||||
return addr & MAKE_64BIT_MASK(0, 32);
|
addr = (uint32_t)addr;
|
||||||
}
|
} else if (extract32(addr, 24, 4) != 0) {
|
||||||
if (extract32(addr, 24, 4) != 0) {
|
|
||||||
/* I/O address space */
|
/* I/O address space */
|
||||||
return addr | MAKE_64BIT_MASK(32, 32);
|
addr = (int32_t)addr;
|
||||||
}
|
|
||||||
/* PDC address space */
|
|
||||||
return (addr & MAKE_64BIT_MASK(0, 24)) | MAKE_64BIT_MASK(60, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static hwaddr hppa_abs_to_phys(CPUHPPAState *env, vaddr addr)
|
|
||||||
{
|
|
||||||
if (!hppa_is_pa20(env)) {
|
|
||||||
return addr;
|
|
||||||
} else if (env->psw & PSW_W) {
|
|
||||||
return hppa_abs_to_phys_pa2_w1(addr);
|
|
||||||
} else {
|
} else {
|
||||||
return hppa_abs_to_phys_pa2_w0(addr);
|
/* PDC address space */
|
||||||
|
addr &= MAKE_64BIT_MASK(0, 24);
|
||||||
|
addr |= -1ull << (TARGET_PHYS_ADDR_SPACE_BITS - 4);
|
||||||
}
|
}
|
||||||
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HPPATLBEntry *hppa_find_tlb(CPUHPPAState *env, vaddr addr)
|
static HPPATLBEntry *hppa_find_tlb(CPUHPPAState *env, vaddr addr)
|
||||||
@ -161,9 +159,22 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||||||
*tlb_entry = NULL;
|
*tlb_entry = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Virtual translation disabled. Direct map virtual to physical. */
|
/* Virtual translation disabled. Map absolute to physical. */
|
||||||
if (mmu_idx == MMU_PHYS_IDX) {
|
if (MMU_IDX_MMU_DISABLED(mmu_idx)) {
|
||||||
phys = addr;
|
switch (mmu_idx) {
|
||||||
|
case MMU_ABS_W_IDX:
|
||||||
|
phys = hppa_abs_to_phys_pa2_w1(addr);
|
||||||
|
break;
|
||||||
|
case MMU_ABS_IDX:
|
||||||
|
if (hppa_is_pa20(env)) {
|
||||||
|
phys = hppa_abs_to_phys_pa2_w0(addr);
|
||||||
|
} else {
|
||||||
|
phys = (uint32_t)addr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
goto egress;
|
goto egress;
|
||||||
}
|
}
|
||||||
@ -261,7 +272,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
egress:
|
egress:
|
||||||
*pphys = phys = hppa_abs_to_phys(env, phys);
|
*pphys = phys;
|
||||||
*pprot = prot;
|
*pprot = prot;
|
||||||
trace_hppa_tlb_get_physical_address(env, ret, prot, addr, phys);
|
trace_hppa_tlb_get_physical_address(env, ret, prot, addr, phys);
|
||||||
return ret;
|
return ret;
|
||||||
@ -271,16 +282,15 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
|||||||
{
|
{
|
||||||
HPPACPU *cpu = HPPA_CPU(cs);
|
HPPACPU *cpu = HPPA_CPU(cs);
|
||||||
hwaddr phys;
|
hwaddr phys;
|
||||||
int prot, excp;
|
int prot, excp, mmu_idx;
|
||||||
|
|
||||||
/* If the (data) mmu is disabled, bypass translation. */
|
/* If the (data) mmu is disabled, bypass translation. */
|
||||||
/* ??? We really ought to know if the code mmu is disabled too,
|
/* ??? We really ought to know if the code mmu is disabled too,
|
||||||
in order to get the correct debugging dumps. */
|
in order to get the correct debugging dumps. */
|
||||||
if (!(cpu->env.psw & PSW_D)) {
|
mmu_idx = (cpu->env.psw & PSW_D ? MMU_KERNEL_IDX :
|
||||||
return hppa_abs_to_phys(&cpu->env, addr);
|
cpu->env.psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
|
||||||
}
|
|
||||||
|
|
||||||
excp = hppa_get_physical_address(&cpu->env, addr, MMU_KERNEL_IDX, 0,
|
excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0,
|
||||||
&phys, &prot, NULL);
|
&phys, &prot, NULL);
|
||||||
|
|
||||||
/* Since we're translating for debugging, the only error that is a
|
/* Since we're translating for debugging, the only error that is a
|
||||||
@ -367,8 +377,8 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
|
|||||||
trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx);
|
trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx);
|
||||||
|
|
||||||
/* Failure. Raise the indicated exception. */
|
/* Failure. Raise the indicated exception. */
|
||||||
raise_exception_with_ior(env, excp, retaddr,
|
raise_exception_with_ior(env, excp, retaddr, addr,
|
||||||
addr, mmu_idx == MMU_PHYS_IDX);
|
MMU_IDX_MMU_DISABLED(mmu_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_hppa_tlb_fill_success(env, addr & TARGET_PAGE_MASK,
|
trace_hppa_tlb_fill_success(env, addr & TARGET_PAGE_MASK,
|
||||||
@ -450,7 +460,7 @@ static void itlbt_pa20(CPUHPPAState *env, target_ulong r1,
|
|||||||
int mask_shift;
|
int mask_shift;
|
||||||
|
|
||||||
mask_shift = 2 * (r1 & 0xf);
|
mask_shift = 2 * (r1 & 0xf);
|
||||||
va_size = TARGET_PAGE_SIZE << mask_shift;
|
va_size = (uint64_t)TARGET_PAGE_SIZE << mask_shift;
|
||||||
va_b &= -va_size;
|
va_b &= -va_size;
|
||||||
va_e = va_b + va_size - 1;
|
va_e = va_b + va_size - 1;
|
||||||
|
|
||||||
@ -459,7 +469,14 @@ static void itlbt_pa20(CPUHPPAState *env, target_ulong r1,
|
|||||||
|
|
||||||
ent->itree.start = va_b;
|
ent->itree.start = va_b;
|
||||||
ent->itree.last = va_e;
|
ent->itree.last = va_e;
|
||||||
ent->pa = (r1 << 7) & (TARGET_PAGE_MASK << mask_shift);
|
|
||||||
|
/* Extract all 52 bits present in the page table entry. */
|
||||||
|
ent->pa = r1 << (TARGET_PAGE_BITS - 5);
|
||||||
|
/* Align per the page size. */
|
||||||
|
ent->pa &= TARGET_PAGE_MASK << mask_shift;
|
||||||
|
/* Ignore the bits beyond physical address space. */
|
||||||
|
ent->pa = sextract64(ent->pa, 0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||||
|
|
||||||
ent->t = extract64(r2, 61, 1);
|
ent->t = extract64(r2, 61, 1);
|
||||||
ent->d = extract64(r2, 60, 1);
|
ent->d = extract64(r2, 60, 1);
|
||||||
ent->b = extract64(r2, 59, 1);
|
ent->b = extract64(r2, 59, 1);
|
||||||
@ -505,7 +522,7 @@ static void ptlb_work(CPUState *cpu, run_on_cpu_data data)
|
|||||||
*/
|
*/
|
||||||
end = start & 0xf;
|
end = start & 0xf;
|
||||||
start &= TARGET_PAGE_MASK;
|
start &= TARGET_PAGE_MASK;
|
||||||
end = TARGET_PAGE_SIZE << (2 * end);
|
end = (vaddr)TARGET_PAGE_SIZE << (2 * end);
|
||||||
end = start + end - 1;
|
end = start + end - 1;
|
||||||
|
|
||||||
hppa_flush_tlb_range(env, start, end);
|
hppa_flush_tlb_range(env, start, end);
|
||||||
|
@ -338,7 +338,7 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr,
|
|||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
return page_check_range(addr, 1, want);
|
return page_check_range(addr, 1, want);
|
||||||
#else
|
#else
|
||||||
int prot, excp;
|
int prot, excp, mmu_idx;
|
||||||
hwaddr phys;
|
hwaddr phys;
|
||||||
|
|
||||||
trace_hppa_tlb_probe(addr, level, want);
|
trace_hppa_tlb_probe(addr, level, want);
|
||||||
@ -347,7 +347,8 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
excp = hppa_get_physical_address(env, addr, level, 0, &phys,
|
mmu_idx = PRIV_P_TO_MMU_IDX(level, env->psw & PSW_P);
|
||||||
|
excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys,
|
||||||
&prot, NULL);
|
&prot, NULL);
|
||||||
if (excp >= 0) {
|
if (excp >= 0) {
|
||||||
if (env->psw & PSW_Q) {
|
if (env->psw & PSW_Q) {
|
||||||
|
@ -69,19 +69,24 @@ typedef struct DisasContext {
|
|||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
#define UNALIGN(C) (C)->unalign
|
#define UNALIGN(C) (C)->unalign
|
||||||
|
#define MMU_DISABLED(C) false
|
||||||
#else
|
#else
|
||||||
#define UNALIGN(C) MO_ALIGN
|
#define UNALIGN(C) MO_ALIGN
|
||||||
|
#define MMU_DISABLED(C) MMU_IDX_MMU_DISABLED((C)->mmu_idx)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
|
/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
|
||||||
static int expand_sm_imm(DisasContext *ctx, int val)
|
static int expand_sm_imm(DisasContext *ctx, int val)
|
||||||
{
|
{
|
||||||
if (val & PSW_SM_E) {
|
/* Keep unimplemented bits disabled -- see cpu_hppa_put_psw. */
|
||||||
val = (val & ~PSW_SM_E) | PSW_E;
|
if (ctx->is_pa20) {
|
||||||
}
|
if (val & PSW_SM_W) {
|
||||||
if (val & PSW_SM_W) {
|
val |= PSW_W;
|
||||||
val = (val & ~PSW_SM_W) | PSW_W;
|
}
|
||||||
|
val &= ~(PSW_SM_W | PSW_SM_E | PSW_G);
|
||||||
|
} else {
|
||||||
|
val &= ~(PSW_SM_W | PSW_SM_E | PSW_O);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -1372,7 +1377,7 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
|
|||||||
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
@ -1390,7 +1395,7 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
|
|||||||
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
@ -1408,7 +1413,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
|
|||||||
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
@ -1426,7 +1431,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
|
|||||||
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
assert(ctx->null_cond.c == TCG_COND_NEVER);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
@ -2294,7 +2299,7 @@ static bool trans_probe(DisasContext *ctx, arg_probe *a)
|
|||||||
form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
|
form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
|
||||||
|
|
||||||
if (a->imm) {
|
if (a->imm) {
|
||||||
level = tcg_constant_i32(a->ri);
|
level = tcg_constant_i32(a->ri & 3);
|
||||||
} else {
|
} else {
|
||||||
level = tcg_temp_new_i32();
|
level = tcg_temp_new_i32();
|
||||||
tcg_gen_extrl_i64_i32(level, load_gpr(ctx, a->ri));
|
tcg_gen_extrl_i64_i32(level, load_gpr(ctx, a->ri));
|
||||||
@ -3075,7 +3080,7 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
|
form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
|
||||||
a->disp, a->sp, a->m, ctx->mmu_idx == MMU_PHYS_IDX);
|
a->disp, a->sp, a->m, MMU_DISABLED(ctx));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For hppa1.1, LDCW is undefined unless aligned mod 16.
|
* For hppa1.1, LDCW is undefined unless aligned mod 16.
|
||||||
@ -3105,7 +3110,7 @@ static bool trans_stby(DisasContext *ctx, arg_stby *a)
|
|||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
|
form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
val = load_gpr(ctx, a->r);
|
val = load_gpr(ctx, a->r);
|
||||||
if (a->a) {
|
if (a->a) {
|
||||||
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
|
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
|
||||||
@ -3139,7 +3144,7 @@ static bool trans_stdby(DisasContext *ctx, arg_stby *a)
|
|||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
|
form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
MMU_DISABLED(ctx));
|
||||||
val = load_gpr(ctx, a->r);
|
val = load_gpr(ctx, a->r);
|
||||||
if (a->a) {
|
if (a->a) {
|
||||||
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
|
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
|
||||||
@ -3167,7 +3172,7 @@ static bool trans_lda(DisasContext *ctx, arg_ldst *a)
|
|||||||
int hold_mmu_idx = ctx->mmu_idx;
|
int hold_mmu_idx = ctx->mmu_idx;
|
||||||
|
|
||||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||||
ctx->mmu_idx = MMU_PHYS_IDX;
|
ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
|
||||||
trans_ld(ctx, a);
|
trans_ld(ctx, a);
|
||||||
ctx->mmu_idx = hold_mmu_idx;
|
ctx->mmu_idx = hold_mmu_idx;
|
||||||
return true;
|
return true;
|
||||||
@ -3178,7 +3183,7 @@ static bool trans_sta(DisasContext *ctx, arg_ldst *a)
|
|||||||
int hold_mmu_idx = ctx->mmu_idx;
|
int hold_mmu_idx = ctx->mmu_idx;
|
||||||
|
|
||||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||||
ctx->mmu_idx = MMU_PHYS_IDX;
|
ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
|
||||||
trans_st(ctx, a);
|
trans_st(ctx, a);
|
||||||
ctx->mmu_idx = hold_mmu_idx;
|
ctx->mmu_idx = hold_mmu_idx;
|
||||||
return true;
|
return true;
|
||||||
@ -4430,7 +4435,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||||||
ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
|
ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
|
||||||
ctx->mmu_idx = (ctx->tb_flags & PSW_D
|
ctx->mmu_idx = (ctx->tb_flags & PSW_D
|
||||||
? PRIV_P_TO_MMU_IDX(ctx->privilege, ctx->tb_flags & PSW_P)
|
? PRIV_P_TO_MMU_IDX(ctx->privilege, ctx->tb_flags & PSW_P)
|
||||||
: MMU_PHYS_IDX);
|
: ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
|
||||||
|
|
||||||
/* Recover the IAOQ values from the GVA + PRIV. */
|
/* Recover the IAOQ values from the GVA + PRIV. */
|
||||||
uint64_t cs_base = ctx->base.tb->cs_base;
|
uint64_t cs_base = ctx->base.tb->cs_base;
|
||||||
|
Loading…
Reference in New Issue
Block a user