Merge branch 'for-upstream' of git://repo.or.cz/qemu/agraf
* 'for-upstream' of git://repo.or.cz/qemu/agraf: (21 commits) PPC: E500: Populate L1CFG0 SPR PPC: e500mc: Enable processor control PPC: E500: Implement msgsnd PPC: E500: Implement msgclr PPC: Enable doorbell excp handlers PPC: Add CPU feature for processor control PPC: E500: Add doorbell defines PPC: E500: Add some more excp vectors KVM: Fix compilation on non-x86 PPC: booke206: move avail check to tlbwe PPC: booke206: Check for TLB overrun PPC: booke206: Implement tlbilx PPC: booke206: Check for min/max TLB entry size PPC: booke: add tlbnps handling PPC: booke206: allow NULL raddr in ppcmas_tlb_check PPC: rename msync to msync_4xx PPC: e500: msync is 440 only, e500 has real sync PPC: e500mc: add missing IVORs to bitmap PPC: Add IVOR 38-42 PPC: KVM: Update HIOR code to new interface ...
This commit is contained in:
commit
f0c4d3ebc3
@ -1306,7 +1306,11 @@ int kvm_has_many_ioeventfds(void)
|
||||
|
||||
int kvm_has_gsi_routing(void)
|
||||
{
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kvm_allows_irq0_override(void)
|
||||
|
@ -265,12 +265,9 @@ struct kvm_debug_exit_arch {
|
||||
struct kvm_guest_debug_arch {
|
||||
};
|
||||
|
||||
#define KVM_REG_MASK 0x001f
|
||||
#define KVM_REG_EXT_MASK 0xffe0
|
||||
#define KVM_REG_GPR 0x0000
|
||||
#define KVM_REG_FPR 0x0020
|
||||
#define KVM_REG_QPR 0x0040
|
||||
#define KVM_REG_FQPR 0x0060
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
};
|
||||
|
||||
#define KVM_INTERRUPT_SET -1U
|
||||
#define KVM_INTERRUPT_UNSET -2U
|
||||
@ -327,6 +324,6 @@ struct kvm_book3e_206_tlb_params {
|
||||
__u32 reserved[8];
|
||||
};
|
||||
|
||||
#define KVM_ONE_REG_PPC_HIOR KVM_ONE_REG_PPC | 0x100
|
||||
#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
|
||||
|
||||
#endif /* __LINUX_KVM_POWERPC_H */
|
||||
|
@ -22,6 +22,16 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Additions to this struct must only occur at the end, and should be
|
||||
* accompanied by a KVM_MAGIC_FEAT flag to advertise that they are present
|
||||
* (albeit not necessarily relevant to the current target hardware platform).
|
||||
*
|
||||
* Struct fields are always 32 or 64 bit aligned, depending on them being 32
|
||||
* or 64 bit wide respectively.
|
||||
*
|
||||
* See Documentation/virtual/kvm/ppc-pv.txt
|
||||
*/
|
||||
struct kvm_vcpu_arch_shared {
|
||||
__u64 scratch1;
|
||||
__u64 scratch2;
|
||||
@ -33,11 +43,35 @@ struct kvm_vcpu_arch_shared {
|
||||
__u64 sprg3;
|
||||
__u64 srr0;
|
||||
__u64 srr1;
|
||||
__u64 dar;
|
||||
__u64 dar; /* dear on BookE */
|
||||
__u64 msr;
|
||||
__u32 dsisr;
|
||||
__u32 int_pending; /* Tells the guest if we have an interrupt */
|
||||
__u32 sr[16];
|
||||
__u32 mas0;
|
||||
__u32 mas1;
|
||||
__u64 mas7_3;
|
||||
__u64 mas2;
|
||||
__u32 mas4;
|
||||
__u32 mas6;
|
||||
__u32 esr;
|
||||
__u32 pir;
|
||||
|
||||
/*
|
||||
* SPRG4-7 are user-readable, so we can only keep these consistent
|
||||
* between the shared area and the real registers when there's an
|
||||
* intervening exit to KVM. This also applies to SPRG3 on some
|
||||
* chips.
|
||||
*
|
||||
* This suffices for access by guest userspace, since in PR-mode
|
||||
* KVM, an exit must occur when changing the guest's MSR[PR].
|
||||
* If the guest kernel writes to SPRG3-7 via the shared area, it
|
||||
* must also use the shared area for reading while in kernel space.
|
||||
*/
|
||||
__u64 sprg4;
|
||||
__u64 sprg5;
|
||||
__u64 sprg6;
|
||||
__u64 sprg7;
|
||||
};
|
||||
|
||||
#define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */
|
||||
@ -47,7 +81,10 @@ struct kvm_vcpu_arch_shared {
|
||||
|
||||
#define KVM_FEATURE_MAGIC_PAGE 1
|
||||
|
||||
#define KVM_MAGIC_FEAT_SR (1 << 0)
|
||||
#define KVM_MAGIC_FEAT_SR (1 << 0)
|
||||
|
||||
/* MASn, ESR, PIR, and high SPRGs */
|
||||
#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1)
|
||||
|
||||
|
||||
#endif /* __POWERPC_KVM_PARA_H__ */
|
||||
|
@ -41,4 +41,13 @@ struct kvm_debug_exit_arch {
|
||||
struct kvm_guest_debug_arch {
|
||||
};
|
||||
|
||||
#define KVM_SYNC_PREFIX (1UL << 0)
|
||||
#define KVM_SYNC_GPRS (1UL << 1)
|
||||
#define KVM_SYNC_ACRS (1UL << 2)
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
__u64 prefix; /* prefix register */
|
||||
__u64 gprs[16]; /* general purpose registers */
|
||||
__u32 acrs[16]; /* access registers */
|
||||
};
|
||||
#endif
|
||||
|
@ -189,5 +189,6 @@
|
||||
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
|
||||
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
|
||||
#define HV_STATUS_INVALID_ALIGNMENT 4
|
||||
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
|
||||
|
||||
#endif
|
||||
|
@ -321,4 +321,8 @@ struct kvm_xcrs {
|
||||
__u64 padding[16];
|
||||
};
|
||||
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
};
|
||||
|
||||
#endif /* _ASM_X86_KVM_H */
|
||||
|
@ -162,6 +162,7 @@ struct kvm_pit_config {
|
||||
#define KVM_EXIT_INTERNAL_ERROR 17
|
||||
#define KVM_EXIT_OSI 18
|
||||
#define KVM_EXIT_PAPR_HCALL 19
|
||||
#define KVM_EXIT_S390_UCONTROL 20
|
||||
|
||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||
#define KVM_INTERNAL_ERROR_EMULATION 1
|
||||
@ -249,6 +250,11 @@ struct kvm_run {
|
||||
#define KVM_S390_RESET_CPU_INIT 8
|
||||
#define KVM_S390_RESET_IPL 16
|
||||
__u64 s390_reset_flags;
|
||||
/* KVM_EXIT_S390_UCONTROL */
|
||||
struct {
|
||||
__u64 trans_exc_code;
|
||||
__u32 pgm_code;
|
||||
} s390_ucontrol;
|
||||
/* KVM_EXIT_DCR */
|
||||
struct {
|
||||
__u32 dcrn;
|
||||
@ -273,6 +279,20 @@ struct kvm_run {
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
|
||||
/*
|
||||
* shared registers between kvm and userspace.
|
||||
* kvm_valid_regs specifies the register classes set by the host
|
||||
* kvm_dirty_regs specified the register classes dirtied by userspace
|
||||
* struct kvm_sync_regs is architecture specific, as well as the
|
||||
* bits for kvm_valid_regs and kvm_dirty_regs
|
||||
*/
|
||||
__u64 kvm_valid_regs;
|
||||
__u64 kvm_dirty_regs;
|
||||
union {
|
||||
struct kvm_sync_regs regs;
|
||||
char padding[1024];
|
||||
} s;
|
||||
};
|
||||
|
||||
/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
|
||||
@ -371,6 +391,7 @@ struct kvm_s390_psw {
|
||||
#define KVM_S390_INT_VIRTIO 0xffff2603u
|
||||
#define KVM_S390_INT_SERVICE 0xffff2401u
|
||||
#define KVM_S390_INT_EMERGENCY 0xffff1201u
|
||||
#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
|
||||
|
||||
struct kvm_s390_interrupt {
|
||||
__u32 type;
|
||||
@ -430,6 +451,11 @@ struct kvm_ppc_pvinfo {
|
||||
|
||||
#define KVMIO 0xAE
|
||||
|
||||
/* machine type bits, to be used as argument to KVM_CREATE_VM */
|
||||
#define KVM_VM_S390_UCONTROL 1
|
||||
|
||||
#define KVM_S390_SIE_PAGE_OFFSET 1
|
||||
|
||||
/*
|
||||
* ioctls for /dev/kvm fds:
|
||||
*/
|
||||
@ -558,6 +584,10 @@ struct kvm_ppc_pvinfo {
|
||||
#define KVM_CAP_PPC_PAPR 68
|
||||
#define KVM_CAP_SW_TLB 69
|
||||
#define KVM_CAP_ONE_REG 70
|
||||
#define KVM_CAP_S390_GMAP 71
|
||||
#define KVM_CAP_TSC_DEADLINE_TIMER 72
|
||||
#define KVM_CAP_S390_UCONTROL 73
|
||||
#define KVM_CAP_SYNC_REGS 74
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@ -654,30 +684,33 @@ struct kvm_dirty_tlb {
|
||||
|
||||
/* Available with KVM_CAP_ONE_REG */
|
||||
|
||||
#define KVM_ONE_REG_GENERIC 0x0000000000000000ULL
|
||||
#define KVM_REG_ARCH_MASK 0xff00000000000000ULL
|
||||
#define KVM_REG_GENERIC 0x0000000000000000ULL
|
||||
|
||||
/*
|
||||
* Architecture specific registers are to be defined in arch headers and
|
||||
* ORed with the arch identifier.
|
||||
*/
|
||||
#define KVM_ONE_REG_PPC 0x1000000000000000ULL
|
||||
#define KVM_ONE_REG_X86 0x2000000000000000ULL
|
||||
#define KVM_ONE_REG_IA64 0x3000000000000000ULL
|
||||
#define KVM_ONE_REG_ARM 0x4000000000000000ULL
|
||||
#define KVM_ONE_REG_S390 0x5000000000000000ULL
|
||||
#define KVM_REG_PPC 0x1000000000000000ULL
|
||||
#define KVM_REG_X86 0x2000000000000000ULL
|
||||
#define KVM_REG_IA64 0x3000000000000000ULL
|
||||
#define KVM_REG_ARM 0x4000000000000000ULL
|
||||
#define KVM_REG_S390 0x5000000000000000ULL
|
||||
|
||||
#define KVM_REG_SIZE_SHIFT 52
|
||||
#define KVM_REG_SIZE_MASK 0x00f0000000000000ULL
|
||||
#define KVM_REG_SIZE_U8 0x0000000000000000ULL
|
||||
#define KVM_REG_SIZE_U16 0x0010000000000000ULL
|
||||
#define KVM_REG_SIZE_U32 0x0020000000000000ULL
|
||||
#define KVM_REG_SIZE_U64 0x0030000000000000ULL
|
||||
#define KVM_REG_SIZE_U128 0x0040000000000000ULL
|
||||
#define KVM_REG_SIZE_U256 0x0050000000000000ULL
|
||||
#define KVM_REG_SIZE_U512 0x0060000000000000ULL
|
||||
#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
|
||||
|
||||
struct kvm_one_reg {
|
||||
__u64 id;
|
||||
union {
|
||||
__u8 reg8;
|
||||
__u16 reg16;
|
||||
__u32 reg32;
|
||||
__u64 reg64;
|
||||
__u8 reg128[16];
|
||||
__u8 reg256[32];
|
||||
__u8 reg512[64];
|
||||
__u8 reg1024[128];
|
||||
} u;
|
||||
__u64 addr;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -698,6 +731,17 @@ struct kvm_one_reg {
|
||||
struct kvm_userspace_memory_region)
|
||||
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
|
||||
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
|
||||
|
||||
/* enable ucontrol for s390 */
|
||||
struct kvm_s390_ucas_mapping {
|
||||
__u64 user_addr;
|
||||
__u64 vcpu_addr;
|
||||
__u64 length;
|
||||
};
|
||||
#define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
|
||||
#define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
|
||||
#define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long)
|
||||
|
||||
/* Device model IOC */
|
||||
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
|
||||
#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
|
||||
@ -809,7 +853,7 @@ struct kvm_one_reg {
|
||||
/* Available with KVM_CAP_SW_TLB */
|
||||
#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
|
||||
/* Available with KVM_CAP_ONE_REG */
|
||||
#define KVM_GET_ONE_REG _IOWR(KVMIO, 0xab, struct kvm_one_reg)
|
||||
#define KVM_GET_ONE_REG _IOW(KVMIO, 0xab, struct kvm_one_reg)
|
||||
#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
|
||||
|
||||
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
|
||||
|
@ -26,4 +26,3 @@
|
||||
#include <asm/kvm_para.h>
|
||||
|
||||
#endif /* __LINUX_KVM_PARA_H */
|
||||
|
||||
|
@ -135,13 +135,13 @@ static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p,
|
||||
vr->num = num;
|
||||
vr->desc = p;
|
||||
vr->avail = p + num*sizeof(struct vring_desc);
|
||||
vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
|
||||
& ~(align - 1));
|
||||
vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__u16)
|
||||
+ align-1) & ~(align - 1));
|
||||
}
|
||||
|
||||
static __inline__ unsigned vring_size(unsigned int num, unsigned long align)
|
||||
{
|
||||
return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
|
||||
return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
|
||||
+ align - 1) & ~(align - 1))
|
||||
+ sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
|
||||
}
|
||||
|
@ -187,7 +187,10 @@ enum {
|
||||
POWERPC_EXCP_EPERFM = 35, /* Embedded performance monitor interrupt */
|
||||
POWERPC_EXCP_DOORI = 36, /* Embedded doorbell interrupt */
|
||||
POWERPC_EXCP_DOORCI = 37, /* Embedded doorbell critical interrupt */
|
||||
/* Vectors 38 to 63 are reserved */
|
||||
POWERPC_EXCP_GDOORI = 38, /* Embedded guest doorbell interrupt */
|
||||
POWERPC_EXCP_GDOORCI = 39, /* Embedded guest doorbell critical interrupt*/
|
||||
POWERPC_EXCP_HYPPRIV = 41, /* Embedded hypervisor priv instruction */
|
||||
/* Vectors 42 to 63 are reserved */
|
||||
/* Exceptions defined in the PowerPC server specification */
|
||||
POWERPC_EXCP_RESET = 64, /* System reset exception */
|
||||
POWERPC_EXCP_DSEG = 65, /* Data segment exception */
|
||||
@ -854,6 +857,22 @@ enum {
|
||||
/* number of possible TLBs */
|
||||
#define BOOKE206_MAX_TLBN 4
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Embedded.Processor Control */
|
||||
|
||||
#define DBELL_TYPE_SHIFT 27
|
||||
#define DBELL_TYPE_MASK (0x1f << DBELL_TYPE_SHIFT)
|
||||
#define DBELL_TYPE_DBELL (0x00 << DBELL_TYPE_SHIFT)
|
||||
#define DBELL_TYPE_DBELL_CRIT (0x01 << DBELL_TYPE_SHIFT)
|
||||
#define DBELL_TYPE_G_DBELL (0x02 << DBELL_TYPE_SHIFT)
|
||||
#define DBELL_TYPE_G_DBELL_CRIT (0x03 << DBELL_TYPE_SHIFT)
|
||||
#define DBELL_TYPE_G_DBELL_MC (0x04 << DBELL_TYPE_SHIFT)
|
||||
|
||||
#define DBELL_BRDCAST (1 << 26)
|
||||
#define DBELL_LPIDTAG_SHIFT 14
|
||||
#define DBELL_LPIDTAG_MASK (0xfff << DBELL_LPIDTAG_SHIFT)
|
||||
#define DBELL_PIRTAG_MASK 0x3fff
|
||||
|
||||
/*****************************************************************************/
|
||||
/* The whole PowerPC CPU context */
|
||||
#define NB_MMU_MODES 3
|
||||
@ -1355,6 +1374,10 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
|
||||
#define SPR_BOOKE_DVC2 (0x13F)
|
||||
#define SPR_BOOKE_TSR (0x150)
|
||||
#define SPR_BOOKE_TCR (0x154)
|
||||
#define SPR_BOOKE_TLB0PS (0x158)
|
||||
#define SPR_BOOKE_TLB1PS (0x159)
|
||||
#define SPR_BOOKE_TLB2PS (0x15A)
|
||||
#define SPR_BOOKE_TLB3PS (0x15B)
|
||||
#define SPR_BOOKE_IVOR0 (0x190)
|
||||
#define SPR_BOOKE_IVOR1 (0x191)
|
||||
#define SPR_BOOKE_IVOR2 (0x192)
|
||||
@ -1371,6 +1394,11 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
|
||||
#define SPR_BOOKE_IVOR13 (0x19D)
|
||||
#define SPR_BOOKE_IVOR14 (0x19E)
|
||||
#define SPR_BOOKE_IVOR15 (0x19F)
|
||||
#define SPR_BOOKE_IVOR38 (0x1B0)
|
||||
#define SPR_BOOKE_IVOR39 (0x1B1)
|
||||
#define SPR_BOOKE_IVOR40 (0x1B2)
|
||||
#define SPR_BOOKE_IVOR41 (0x1B3)
|
||||
#define SPR_BOOKE_IVOR42 (0x1B4)
|
||||
#define SPR_BOOKE_SPEFSCR (0x200)
|
||||
#define SPR_Exxx_BBEAR (0x201)
|
||||
#define SPR_Exxx_BBTAR (0x202)
|
||||
@ -1888,8 +1916,10 @@ enum {
|
||||
PPC2_VSX = 0x0000000000000002ULL,
|
||||
/* Decimal Floating Point (DFP) */
|
||||
PPC2_DFP = 0x0000000000000004ULL,
|
||||
/* Embedded.Processor Control */
|
||||
PPC2_PRCNTL = 0x0000000000000008ULL,
|
||||
|
||||
#define PPC_TCG_INSNS2 (PPC2_BOOKE206)
|
||||
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL)
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -2103,6 +2133,10 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
|
||||
ea &= (1 << (tlb_bits - ways_bits)) - 1;
|
||||
r = (ea << ways_bits) | way;
|
||||
|
||||
if (r >= booke206_tlb_size(env, tlbn)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* bump up to tlbn index */
|
||||
for (i = 0; i < tlbn; i++) {
|
||||
r += booke206_tlb_size(env, i);
|
||||
@ -2111,6 +2145,27 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
|
||||
return &env->tlb.tlbm[r];
|
||||
}
|
||||
|
||||
/* returns bitmap of supported page sizes for a given TLB */
|
||||
static inline uint32_t booke206_tlbnps(CPUState *env, const int tlbn)
|
||||
{
|
||||
bool mav2 = false;
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (mav2) {
|
||||
ret = env->spr[SPR_BOOKE_TLB0PS + tlbn];
|
||||
} else {
|
||||
uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
|
||||
uint32_t min = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
|
||||
uint32_t max = (tlbncfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
|
||||
int i;
|
||||
for (i = min; i <= max; i++) {
|
||||
ret |= (1 << (i << 1));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern void (*cpu_ppc_hypercall)(CPUState *);
|
||||
|
@ -1298,13 +1298,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
|
||||
int tlbm_size;
|
||||
|
||||
tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
|
||||
|
||||
if (tlbncfg & TLBnCFG_AVAIL) {
|
||||
tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
|
||||
} else {
|
||||
tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
|
||||
tlbm_size <<= 1;
|
||||
}
|
||||
tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
|
||||
|
||||
return 1024ULL << tlbm_size;
|
||||
}
|
||||
@ -1338,7 +1332,10 @@ int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
|
||||
if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
|
||||
return -1;
|
||||
}
|
||||
*raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
|
||||
|
||||
if (raddrp) {
|
||||
*raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1445,6 +1442,9 @@ static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
|
||||
|
||||
for (j = 0; j < ways; j++) {
|
||||
tlb = booke206_get_tlbm(env, i, address, j);
|
||||
if (!tlb) {
|
||||
continue;
|
||||
}
|
||||
ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
|
||||
rw, access_type);
|
||||
if (ret != -1) {
|
||||
@ -2698,22 +2698,10 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
|
||||
"Performance counter exception is not implemented yet !\n");
|
||||
goto store_next;
|
||||
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
|
||||
/* XXX: TODO */
|
||||
cpu_abort(env,
|
||||
"Embedded doorbell interrupt is not implemented yet !\n");
|
||||
goto store_next;
|
||||
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
|
||||
switch (excp_model) {
|
||||
case POWERPC_EXCP_BOOKE:
|
||||
srr0 = SPR_BOOKE_CSRR0;
|
||||
srr1 = SPR_BOOKE_CSRR1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* XXX: TODO */
|
||||
cpu_abort(env, "Embedded doorbell critical interrupt "
|
||||
"is not implemented yet !\n");
|
||||
srr0 = SPR_BOOKE_CSRR0;
|
||||
srr1 = SPR_BOOKE_CSRR1;
|
||||
goto store_next;
|
||||
case POWERPC_EXCP_RESET: /* System reset exception */
|
||||
if (msr_pow) {
|
||||
|
@ -336,6 +336,9 @@ DEF_HELPER_0(booke206_tlbre, void)
|
||||
DEF_HELPER_0(booke206_tlbwe, void)
|
||||
DEF_HELPER_1(booke206_tlbsx, void, tl)
|
||||
DEF_HELPER_1(booke206_tlbivax, void, tl)
|
||||
DEF_HELPER_1(booke206_tlbilx0, void, tl)
|
||||
DEF_HELPER_1(booke206_tlbilx1, void, tl)
|
||||
DEF_HELPER_1(booke206_tlbilx3, void, tl)
|
||||
DEF_HELPER_1(booke206_tlbflush, void, i32)
|
||||
DEF_HELPER_2(booke_setpid, void, i32, tl)
|
||||
DEF_HELPER_1(6xx_tlbd, void, tl)
|
||||
@ -355,6 +358,8 @@ DEF_HELPER_FLAGS_1(load_sr, TCG_CALL_CONST, tl, tl);
|
||||
DEF_HELPER_FLAGS_2(store_sr, TCG_CALL_CONST, void, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
|
||||
DEF_HELPER_1(msgsnd, void, tl)
|
||||
DEF_HELPER_1(msgclr, void, tl)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_3(dlmzb, tl, tl, tl, i32)
|
||||
|
@ -740,6 +740,7 @@ void kvmppc_set_papr(CPUState *env)
|
||||
struct kvm_one_reg reg = {};
|
||||
struct kvm_sregs sregs = {};
|
||||
int ret;
|
||||
uint64_t hior = env->spr[SPR_HIOR];
|
||||
|
||||
cap.cap = KVM_CAP_PPC_PAPR;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
|
||||
@ -755,11 +756,14 @@ void kvmppc_set_papr(CPUState *env)
|
||||
* Once we have qdev CPUs, move HIOR to a qdev property and
|
||||
* remove this chunk.
|
||||
*/
|
||||
reg.id = KVM_ONE_REG_PPC_HIOR;
|
||||
reg.u.reg64 = env->spr[SPR_HIOR];
|
||||
reg.id = KVM_REG_PPC_HIOR;
|
||||
reg.addr = (uintptr_t)&hior;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®);
|
||||
if (ret) {
|
||||
goto fail;
|
||||
fprintf(stderr, "Couldn't set HIOR. Maybe you're running an old \n"
|
||||
"kernel with support for HV KVM but no PAPR PR \n"
|
||||
"KVM in which case things will work. If they don't \n"
|
||||
"please update your host kernel!\n");
|
||||
}
|
||||
|
||||
/* Set SDR1 so kernel space finds the HTAB */
|
||||
|
@ -4228,6 +4228,7 @@ void helper_booke206_tlbwe(void)
|
||||
{
|
||||
uint32_t tlbncfg, tlbn;
|
||||
ppcmas_tlb_t *tlb;
|
||||
uint32_t size_tlb, size_ps;
|
||||
|
||||
switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
|
||||
case MAS0_WQ_ALWAYS:
|
||||
@ -4259,12 +4260,37 @@ void helper_booke206_tlbwe(void)
|
||||
|
||||
tlb = booke206_cur_tlb(env);
|
||||
|
||||
if (!tlb) {
|
||||
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
|
||||
POWERPC_EXCP_INVAL |
|
||||
POWERPC_EXCP_INVAL_INVAL);
|
||||
}
|
||||
|
||||
/* check that we support the targeted size */
|
||||
size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
|
||||
size_ps = booke206_tlbnps(env, tlbn);
|
||||
if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
|
||||
!(size_ps & (1 << size_tlb))) {
|
||||
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
|
||||
POWERPC_EXCP_INVAL |
|
||||
POWERPC_EXCP_INVAL_INVAL);
|
||||
}
|
||||
|
||||
if (msr_gs) {
|
||||
cpu_abort(env, "missing HV implementation\n");
|
||||
}
|
||||
tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
|
||||
env->spr[SPR_BOOKE_MAS3];
|
||||
tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
|
||||
|
||||
/* MAV 1.0 only */
|
||||
if (!(tlbncfg & TLBnCFG_AVAIL)) {
|
||||
/* force !AVAIL TLB entries to correct page size */
|
||||
tlb->mas1 &= ~MAS1_TSIZE_MASK;
|
||||
/* XXX can be configured in MMUCSR0 */
|
||||
tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
|
||||
}
|
||||
|
||||
/* XXX needs to change when supporting 64-bit e500 */
|
||||
tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & 0xffffffff;
|
||||
|
||||
@ -4300,7 +4326,11 @@ void helper_booke206_tlbre(void)
|
||||
ppcmas_tlb_t *tlb = NULL;
|
||||
|
||||
tlb = booke206_cur_tlb(env);
|
||||
booke206_tlb_to_mas(env, tlb);
|
||||
if (!tlb) {
|
||||
env->spr[SPR_BOOKE_MAS1] = 0;
|
||||
} else {
|
||||
booke206_tlb_to_mas(env, tlb);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_booke206_tlbsx(target_ulong address)
|
||||
@ -4319,6 +4349,10 @@ void helper_booke206_tlbsx(target_ulong address)
|
||||
for (j = 0; j < ways; j++) {
|
||||
tlb = booke206_get_tlbm(env, i, address, j);
|
||||
|
||||
if (!tlb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
|
||||
continue;
|
||||
}
|
||||
@ -4362,6 +4396,9 @@ static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
|
||||
|
||||
for (i = 0; i < ways; i++) {
|
||||
ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
|
||||
if (!tlb) {
|
||||
continue;
|
||||
}
|
||||
mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
|
||||
if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
|
||||
!(tlb->mas1 & MAS1_IPROT)) {
|
||||
@ -4395,6 +4432,73 @@ void helper_booke206_tlbivax(target_ulong address)
|
||||
}
|
||||
}
|
||||
|
||||
void helper_booke206_tlbilx0(target_ulong address)
|
||||
{
|
||||
/* XXX missing LPID handling */
|
||||
booke206_flush_tlb(env, -1, 1);
|
||||
}
|
||||
|
||||
void helper_booke206_tlbilx1(target_ulong address)
|
||||
{
|
||||
int i, j;
|
||||
int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
|
||||
ppcmas_tlb_t *tlb = env->tlb.tlbm;
|
||||
int tlb_size;
|
||||
|
||||
/* XXX missing LPID handling */
|
||||
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
|
||||
tlb_size = booke206_tlb_size(env, i);
|
||||
for (j = 0; j < tlb_size; j++) {
|
||||
if (!(tlb[j].mas1 & MAS1_IPROT) &&
|
||||
((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
|
||||
tlb[j].mas1 &= ~MAS1_VALID;
|
||||
}
|
||||
}
|
||||
tlb += booke206_tlb_size(env, i);
|
||||
}
|
||||
tlb_flush(env, 1);
|
||||
}
|
||||
|
||||
void helper_booke206_tlbilx3(target_ulong address)
|
||||
{
|
||||
int i, j;
|
||||
ppcmas_tlb_t *tlb;
|
||||
int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
|
||||
int pid = tid >> MAS6_SPID_SHIFT;
|
||||
int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
|
||||
int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
|
||||
/* XXX check for unsupported isize and raise an invalid opcode then */
|
||||
int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
|
||||
/* XXX implement MAV2 handling */
|
||||
bool mav2 = false;
|
||||
|
||||
/* XXX missing LPID handling */
|
||||
/* flush by pid and ea */
|
||||
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
|
||||
int ways = booke206_tlb_ways(env, i);
|
||||
|
||||
for (j = 0; j < ways; j++) {
|
||||
tlb = booke206_get_tlbm(env, i, address, j);
|
||||
if (!tlb) {
|
||||
continue;
|
||||
}
|
||||
if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
|
||||
(tlb->mas1 & MAS1_IPROT) ||
|
||||
((tlb->mas1 & MAS1_IND) != ind) ||
|
||||
((tlb->mas8 & MAS8_TGS) != sgs)) {
|
||||
continue;
|
||||
}
|
||||
if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
|
||||
/* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
|
||||
continue;
|
||||
}
|
||||
/* XXX e500mc doesn't match SAS, but other cores might */
|
||||
tlb->mas1 &= ~MAS1_VALID;
|
||||
}
|
||||
}
|
||||
tlb_flush(env, 1);
|
||||
}
|
||||
|
||||
void helper_booke206_tlbflush(uint32_t type)
|
||||
{
|
||||
int flags = 0;
|
||||
@ -4410,4 +4514,57 @@ void helper_booke206_tlbflush(uint32_t type)
|
||||
booke206_flush_tlb(env, flags, 1);
|
||||
}
|
||||
|
||||
/* Embedded.Processor Control */
|
||||
static int dbell2irq(target_ulong rb)
|
||||
{
|
||||
int msg = rb & DBELL_TYPE_MASK;
|
||||
int irq = -1;
|
||||
|
||||
switch (msg) {
|
||||
case DBELL_TYPE_DBELL:
|
||||
irq = PPC_INTERRUPT_DOORBELL;
|
||||
break;
|
||||
case DBELL_TYPE_DBELL_CRIT:
|
||||
irq = PPC_INTERRUPT_CDOORBELL;
|
||||
break;
|
||||
case DBELL_TYPE_G_DBELL:
|
||||
case DBELL_TYPE_G_DBELL_CRIT:
|
||||
case DBELL_TYPE_G_DBELL_MC:
|
||||
/* XXX implement */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void helper_msgclr(target_ulong rb)
|
||||
{
|
||||
int irq = dbell2irq(rb);
|
||||
|
||||
if (irq < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
env->pending_interrupts &= ~(1 << irq);
|
||||
}
|
||||
|
||||
void helper_msgsnd(target_ulong rb)
|
||||
{
|
||||
int irq = dbell2irq(rb);
|
||||
int pir = rb & DBELL_PIRTAG_MASK;
|
||||
CPUState *cenv;
|
||||
|
||||
if (irq < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
|
||||
if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
|
||||
cenv->pending_interrupts |= 1 << irq;
|
||||
cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
@ -6088,6 +6088,7 @@ static void gen_tlbwe_booke206(DisasContext *ctx)
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
return;
|
||||
}
|
||||
gen_update_nip(ctx, ctx->nip - 4);
|
||||
gen_helper_booke206_tlbwe();
|
||||
#endif
|
||||
}
|
||||
@ -6110,6 +6111,39 @@ static void gen_tlbivax_booke206(DisasContext *ctx)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_tlbilx_booke206(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
#else
|
||||
TCGv t0;
|
||||
if (unlikely(!ctx->mem_idx)) {
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
return;
|
||||
}
|
||||
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
|
||||
switch((ctx->opcode >> 21) & 0x3) {
|
||||
case 0:
|
||||
gen_helper_booke206_tlbilx0(t0);
|
||||
break;
|
||||
case 1:
|
||||
gen_helper_booke206_tlbilx1(t0);
|
||||
break;
|
||||
case 3:
|
||||
gen_helper_booke206_tlbilx3(t0);
|
||||
break;
|
||||
default:
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free(t0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* wrtee */
|
||||
static void gen_wrtee(DisasContext *ctx)
|
||||
@ -6172,7 +6206,7 @@ static void gen_mbar(DisasContext *ctx)
|
||||
}
|
||||
|
||||
/* msync replaces sync on 440 */
|
||||
static void gen_msync(DisasContext *ctx)
|
||||
static void gen_msync_4xx(DisasContext *ctx)
|
||||
{
|
||||
/* interpreted as no-op */
|
||||
}
|
||||
@ -6186,6 +6220,36 @@ static void gen_icbt_440(DisasContext *ctx)
|
||||
*/
|
||||
}
|
||||
|
||||
/* Embedded.Processor Control */
|
||||
|
||||
static void gen_msgclr(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
#else
|
||||
if (unlikely(ctx->mem_idx == 0)) {
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
return;
|
||||
}
|
||||
|
||||
gen_helper_msgclr(cpu_gpr[rB(ctx->opcode)]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_msgsnd(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
#else
|
||||
if (unlikely(ctx->mem_idx == 0)) {
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
|
||||
return;
|
||||
}
|
||||
|
||||
gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*** Altivec vector extension ***/
|
||||
/* Altivec registers moves */
|
||||
|
||||
@ -8574,13 +8638,18 @@ GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
|
||||
PPC_NONE, PPC2_BOOKE206),
|
||||
GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
|
||||
PPC_NONE, PPC2_BOOKE206),
|
||||
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
|
||||
PPC_NONE, PPC2_BOOKE206),
|
||||
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
|
||||
PPC_NONE, PPC2_PRCNTL),
|
||||
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
|
||||
PPC_NONE, PPC2_PRCNTL),
|
||||
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
|
||||
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
|
||||
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
|
||||
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
|
||||
PPC_BOOKE, PPC2_BOOKE206),
|
||||
GEN_HANDLER_E(msync, 0x1F, 0x16, 0x12, 0x03FFF801,
|
||||
PPC_BOOKE, PPC2_BOOKE206),
|
||||
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
|
||||
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
|
||||
PPC_BOOKE, PPC2_BOOKE206),
|
||||
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
|
||||
|
@ -526,26 +526,27 @@ static void spr_write_excp_prefix (void *opaque, int sprn, int gprn)
|
||||
static void spr_write_excp_vector (void *opaque, int sprn, int gprn)
|
||||
{
|
||||
DisasContext *ctx = opaque;
|
||||
int sprn_offs;
|
||||
|
||||
if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
|
||||
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
|
||||
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR0]));
|
||||
gen_store_spr(sprn, t0);
|
||||
tcg_temp_free(t0);
|
||||
sprn_offs = sprn - SPR_BOOKE_IVOR0;
|
||||
} else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
|
||||
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
|
||||
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR32 + 32]));
|
||||
gen_store_spr(sprn, t0);
|
||||
tcg_temp_free(t0);
|
||||
sprn_offs = sprn - SPR_BOOKE_IVOR32 + 32;
|
||||
} else if (sprn >= SPR_BOOKE_IVOR38 && sprn <= SPR_BOOKE_IVOR42) {
|
||||
sprn_offs = sprn - SPR_BOOKE_IVOR38 + 38;
|
||||
} else {
|
||||
printf("Trying to write an unknown exception vector %d %03x\n",
|
||||
sprn, sprn);
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
|
||||
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
|
||||
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn_offs]));
|
||||
gen_store_spr(sprn, t0);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1434,8 +1435,8 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVOR32, SPR_BOOKE_IVOR33, SPR_BOOKE_IVOR34, SPR_BOOKE_IVOR35,
|
||||
SPR_BOOKE_IVOR36, SPR_BOOKE_IVOR37, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVOR36, SPR_BOOKE_IVOR37, SPR_BOOKE_IVOR38, SPR_BOOKE_IVOR39,
|
||||
SPR_BOOKE_IVOR40, SPR_BOOKE_IVOR41, SPR_BOOKE_IVOR42, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
|
||||
@ -4370,7 +4371,7 @@ static void init_proc_e300 (CPUPPCState *env)
|
||||
PPC_WRTEE | PPC_RFDI | \
|
||||
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
|
||||
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
|
||||
#define POWERPC_INSNS2_e500v1 (PPC2_BOOKE206)
|
||||
#define POWERPC_MSRM_e500v1 (0x000000000606FF30ULL)
|
||||
#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE206)
|
||||
@ -4389,7 +4390,7 @@ static void init_proc_e300 (CPUPPCState *env)
|
||||
PPC_WRTEE | PPC_RFDI | \
|
||||
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
|
||||
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
|
||||
#define POWERPC_INSNS2_e500v2 (PPC2_BOOKE206)
|
||||
#define POWERPC_MSRM_e500v2 (0x000000000606FF30ULL)
|
||||
#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE206)
|
||||
@ -4410,8 +4411,8 @@ static void init_proc_e300 (CPUPPCState *env)
|
||||
PPC_FLOAT | PPC_FLOAT_FRES | \
|
||||
PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \
|
||||
PPC_FLOAT_STFIWX | PPC_WAIT | \
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
|
||||
#define POWERPC_INSNS2_e500mc (PPC2_BOOKE206)
|
||||
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
|
||||
#define POWERPC_INSNS2_e500mc (PPC2_BOOKE206 | PPC2_PRCNTL)
|
||||
#define POWERPC_MSRM_e500mc (0x000000001402FB36ULL)
|
||||
#define POWERPC_MMU_e500mc (POWERPC_MMU_BOOKE206)
|
||||
#define POWERPC_EXCP_e500mc (POWERPC_EXCP_BOOKE)
|
||||
@ -4432,6 +4433,9 @@ enum fsl_e500_version {
|
||||
static void init_proc_e500 (CPUPPCState *env, int version)
|
||||
{
|
||||
uint32_t tlbncfg[2];
|
||||
uint64_t ivor_mask = 0x0000000F0000FFFFULL;
|
||||
uint32_t l1cfg0 = 0x3800 /* 8 ways */
|
||||
| 0x0020; /* 32 kb */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int i;
|
||||
#endif
|
||||
@ -4443,7 +4447,10 @@ static void init_proc_e500 (CPUPPCState *env, int version)
|
||||
* complain when accessing them.
|
||||
* gen_spr_BookE(env, 0x0000000F0000FD7FULL);
|
||||
*/
|
||||
gen_spr_BookE(env, 0x0000000F0000FFFFULL);
|
||||
if (version == fsl_e500mc) {
|
||||
ivor_mask = 0x000003FE0000FFFFULL;
|
||||
}
|
||||
gen_spr_BookE(env, ivor_mask);
|
||||
/* Processor identification */
|
||||
spr_register(env, SPR_BOOKE_PIR, "PIR",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
@ -4480,6 +4487,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
|
||||
tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64);
|
||||
env->dcache_line_size = 64;
|
||||
env->icache_line_size = 64;
|
||||
l1cfg0 |= 0x1000000; /* 64 byte cache block size */
|
||||
break;
|
||||
default:
|
||||
cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
|
||||
@ -4530,7 +4538,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
|
||||
spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
l1cfg0);
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
|
Loading…
Reference in New Issue
Block a user