提交 75f0585f 编写于 作者: B Blue Swirl

Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf

* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf:
  PPC: KVM: Add support for EPR with KVM
  openpic: export e500 epr enable into a ppc.c function
  Update Linux kernel headers
  PPC: e500: Change in-memory order of load blobs
  PPC: Provide zero SVR for -cpu e500mc and e5500
  PPC: E500: Calculate loading blob offsets properly
  openpic: set mixed mode as supported
  openpic: unify gcr mode mask updates
  openpic: move gcr write into a function
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "sysbus.h" #include "sysbus.h"
#include "pci/msi.h" #include "pci/msi.h"
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "ppc.h"
//#define DEBUG_OPENPIC //#define DEBUG_OPENPIC
...@@ -644,6 +645,26 @@ static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val) ...@@ -644,6 +645,26 @@ static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
opp->src[n_IRQ].ivpr); opp->src[n_IRQ].ivpr);
} }
static void openpic_gcr_write(OpenPICState *opp, uint64_t val)
{
bool mpic_proxy = false;
if (val & GCR_RESET) {
openpic_reset(&opp->busdev.qdev);
return;
}
opp->gcr &= ~opp->mpic_mode_mask;
opp->gcr |= val & opp->mpic_mode_mask;
/* Set external proxy mode */
if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
mpic_proxy = true;
}
ppce500_set_mpic_proxy(mpic_proxy);
}
static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
unsigned len) unsigned len)
{ {
...@@ -672,23 +693,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, ...@@ -672,23 +693,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
case 0x1000: /* FRR */ case 0x1000: /* FRR */
break; break;
case 0x1020: /* GCR */ case 0x1020: /* GCR */
if (val & GCR_RESET) { openpic_gcr_write(opp, val);
openpic_reset(&opp->busdev.qdev);
} else if (opp->mpic_mode_mask) {
CPUArchState *env;
int mpic_proxy = 0;
opp->gcr &= ~opp->mpic_mode_mask;
opp->gcr |= val & opp->mpic_mode_mask;
/* Set external proxy mode */
if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
mpic_proxy = 1;
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
env->mpic_proxy = mpic_proxy;
}
}
break; break;
case 0x1080: /* VIR */ case 0x1080: /* VIR */
break; break;
...@@ -1464,6 +1469,7 @@ static int openpic_init(SysBusDevice *dev) ...@@ -1464,6 +1469,7 @@ static int openpic_init(SysBusDevice *dev)
opp->irq_ipi0 = RAVEN_IPI_IRQ; opp->irq_ipi0 = RAVEN_IPI_IRQ;
opp->irq_tim0 = RAVEN_TMR_IRQ; opp->irq_tim0 = RAVEN_TMR_IRQ;
opp->brr1 = -1; opp->brr1 = -1;
opp->mpic_mode_mask = GCR_MODE_MIXED;
list = list_le; list = list_le;
/* Don't map MSI region */ /* Don't map MSI region */
list[2].map = false; list[2].map = false;
......
...@@ -428,6 +428,23 @@ void ppce500_irq_init(CPUPPCState *env) ...@@ -428,6 +428,23 @@ void ppce500_irq_init(CPUPPCState *env)
env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
cpu, PPCE500_INPUT_NB); cpu, PPCE500_INPUT_NB);
} }
/* Enable or Disable the E500 EPR capability */
void ppce500_set_mpic_proxy(bool enabled)
{
CPUPPCState *env;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
env->mpic_proxy = enabled;
if (kvm_enabled()) {
kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
}
}
}
/*****************************************************************************/ /*****************************************************************************/
/* PowerPC time base and decrementer emulation */ /* PowerPC time base and decrementer emulation */
......
...@@ -73,6 +73,8 @@ void ppc6xx_irq_init (CPUPPCState *env); ...@@ -73,6 +73,8 @@ void ppc6xx_irq_init (CPUPPCState *env);
void ppc970_irq_init (CPUPPCState *env); void ppc970_irq_init (CPUPPCState *env);
void ppcPOWER7_irq_init (CPUPPCState *env); void ppcPOWER7_irq_init (CPUPPCState *env);
void ppce500_set_mpic_proxy(bool enabled);
/* PPC machines for OpenBIOS */ /* PPC machines for OpenBIOS */
enum { enum {
ARCH_PREP = 0, ARCH_PREP = 0,
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define UIMAGE_LOAD_BASE 0 #define UIMAGE_LOAD_BASE 0
#define DTC_LOAD_PAD 0x1800000 #define DTC_LOAD_PAD 0x1800000
#define DTC_PAD_MASK 0xFFFFF #define DTC_PAD_MASK 0xFFFFF
#define DTB_MAX_SIZE (8 * 1024 * 1024)
#define INITRD_LOAD_PAD 0x2000000 #define INITRD_LOAD_PAD 0x2000000
#define INITRD_PAD_MASK 0xFFFFFF #define INITRD_PAD_MASK 0xFFFFFF
...@@ -463,7 +464,8 @@ void ppce500_init(PPCE500Params *params) ...@@ -463,7 +464,8 @@ void ppce500_init(PPCE500Params *params)
target_long kernel_size=0; target_long kernel_size=0;
target_ulong dt_base = 0; target_ulong dt_base = 0;
target_ulong initrd_base = 0; target_ulong initrd_base = 0;
target_long initrd_size=0; target_long initrd_size = 0;
target_ulong cur_base = 0;
int i = 0, j, k; int i = 0, j, k;
unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
qemu_irq **irqs, *mpic; qemu_irq **irqs, *mpic;
...@@ -626,12 +628,17 @@ void ppce500_init(PPCE500Params *params) ...@@ -626,12 +628,17 @@ void ppce500_init(PPCE500Params *params)
params->kernel_filename); params->kernel_filename);
exit(1); exit(1);
} }
cur_base = loadaddr + kernel_size;
/* Reserve space for dtb */
dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
cur_base += DTB_MAX_SIZE;
} }
/* Load initrd. */ /* Load initrd. */
if (params->initrd_filename) { if (params->initrd_filename) {
initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) & initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
~INITRD_PAD_MASK;
initrd_size = load_image_targphys(params->initrd_filename, initrd_base, initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
ram_size - initrd_base); ram_size - initrd_base);
...@@ -640,6 +647,8 @@ void ppce500_init(PPCE500Params *params) ...@@ -640,6 +647,8 @@ void ppce500_init(PPCE500Params *params)
params->initrd_filename); params->initrd_filename);
exit(1); exit(1);
} }
cur_base = initrd_base + initrd_size;
} }
/* If we're loading a kernel directly, we must load the device tree too. */ /* If we're loading a kernel directly, we must load the device tree too. */
...@@ -647,13 +656,13 @@ void ppce500_init(PPCE500Params *params) ...@@ -647,13 +656,13 @@ void ppce500_init(PPCE500Params *params)
struct boot_info *boot_info; struct boot_info *boot_info;
int dt_size; int dt_size;
dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
initrd_size); initrd_size);
if (dt_size < 0) { if (dt_size < 0) {
fprintf(stderr, "couldn't load device tree\n"); fprintf(stderr, "couldn't load device tree\n");
exit(1); exit(1);
} }
assert(dt_size < DTB_MAX_SIZE);
boot_info = env->load_info; boot_info = env->load_info;
boot_info->entry = entry; boot_info->entry = entry;
......
...@@ -114,7 +114,10 @@ struct kvm_regs { ...@@ -114,7 +114,10 @@ struct kvm_regs {
/* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */ /* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */
#define KVM_SREGS_E_SPE (1 << 9) #define KVM_SREGS_E_SPE (1 << 9)
/* External Proxy (EXP) -- EPR */ /*
* DEPRECATED! USE ONE_REG FOR THIS ONE!
* External Proxy (EXP) -- EPR
*/
#define KVM_SREGS_EXP (1 << 10) #define KVM_SREGS_EXP (1 << 10)
/* External PID (E.PD) -- EPSC/EPLC */ /* External PID (E.PD) -- EPSC/EPLC */
...@@ -412,5 +415,6 @@ struct kvm_get_htab_header { ...@@ -412,5 +415,6 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84) #define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
#define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85) #define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
#define KVM_REG_PPC_EPR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86)
#endif /* __LINUX_KVM_POWERPC_H */ #endif /* __LINUX_KVM_POWERPC_H */
...@@ -168,6 +168,8 @@ struct kvm_pit_config { ...@@ -168,6 +168,8 @@ struct kvm_pit_config {
#define KVM_EXIT_PAPR_HCALL 19 #define KVM_EXIT_PAPR_HCALL 19
#define KVM_EXIT_S390_UCONTROL 20 #define KVM_EXIT_S390_UCONTROL 20
#define KVM_EXIT_WATCHDOG 21 #define KVM_EXIT_WATCHDOG 21
#define KVM_EXIT_S390_TSCH 22
#define KVM_EXIT_EPR 23
/* For KVM_EXIT_INTERNAL_ERROR */ /* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */ /* Emulate instruction failed. */
...@@ -285,6 +287,19 @@ struct kvm_run { ...@@ -285,6 +287,19 @@ struct kvm_run {
__u64 ret; __u64 ret;
__u64 args[9]; __u64 args[9];
} papr_hcall; } papr_hcall;
/* KVM_EXIT_S390_TSCH */
struct {
__u16 subchannel_id;
__u16 subchannel_nr;
__u32 io_int_parm;
__u32 io_int_word;
__u32 ipb;
__u8 dequeued;
} s390_tsch;
/* KVM_EXIT_EPR */
struct {
__u32 epr;
} epr;
/* Fix the size of the union. */ /* Fix the size of the union. */
char padding[256]; char padding[256];
}; };
...@@ -397,10 +412,20 @@ struct kvm_s390_psw { ...@@ -397,10 +412,20 @@ struct kvm_s390_psw {
#define KVM_S390_PROGRAM_INT 0xfffe0001u #define KVM_S390_PROGRAM_INT 0xfffe0001u
#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u #define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
#define KVM_S390_RESTART 0xfffe0003u #define KVM_S390_RESTART 0xfffe0003u
#define KVM_S390_MCHK 0xfffe1000u
#define KVM_S390_INT_VIRTIO 0xffff2603u #define KVM_S390_INT_VIRTIO 0xffff2603u
#define KVM_S390_INT_SERVICE 0xffff2401u #define KVM_S390_INT_SERVICE 0xffff2401u
#define KVM_S390_INT_EMERGENCY 0xffff1201u #define KVM_S390_INT_EMERGENCY 0xffff1201u
#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u #define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
/* Anything below 0xfffe0000u is taken by INT_IO */
#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \
(((schid)) | \
((ssid) << 16) | \
((cssid) << 18) | \
((ai) << 26))
#define KVM_S390_INT_IO_MIN 0x00000000u
#define KVM_S390_INT_IO_MAX 0xfffdffffu
struct kvm_s390_interrupt { struct kvm_s390_interrupt {
__u32 type; __u32 type;
...@@ -635,6 +660,8 @@ struct kvm_ppc_smmu_info { ...@@ -635,6 +660,8 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_IRQFD_RESAMPLE 82 #define KVM_CAP_IRQFD_RESAMPLE 82
#define KVM_CAP_PPC_BOOKE_WATCHDOG 83 #define KVM_CAP_PPC_BOOKE_WATCHDOG 83
#define KVM_CAP_PPC_HTAB_FD 84 #define KVM_CAP_PPC_HTAB_FD 84
#define KVM_CAP_S390_CSS_SUPPORT 85
#define KVM_CAP_PPC_EPR 86
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
...@@ -846,6 +846,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ...@@ -846,6 +846,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
ret = 0; ret = 0;
break; break;
#endif #endif
case KVM_EXIT_EPR:
dprintf("handle epr\n");
run->epr.epr = ldl_phys(env->mpic_iack);
ret = 0;
break;
default: default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
ret = -1; ret = -1;
...@@ -1057,6 +1062,22 @@ void kvmppc_set_papr(PowerPCCPU *cpu) ...@@ -1057,6 +1062,22 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
} }
} }
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
CPUPPCState *env = &cpu->env;
CPUState *cs = CPU(cpu);
struct kvm_enable_cap cap = {};
int ret;
cap.cap = KVM_CAP_PPC_EPR;
cap.args[0] = mpic_proxy;
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
if (ret && mpic_proxy) {
cpu_abort(env, "This KVM version does not support EPR\n");
}
}
int kvmppc_smt_threads(void) int kvmppc_smt_threads(void)
{ {
return cap_ppc_smt ? cap_ppc_smt : 1; return cap_ppc_smt ? cap_ppc_smt : 1;
......
...@@ -25,6 +25,7 @@ int kvmppc_get_hasidle(CPUPPCState *env); ...@@ -25,6 +25,7 @@ int kvmppc_get_hasidle(CPUPPCState *env);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len); int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level); int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
void kvmppc_set_papr(PowerPCCPU *cpu); void kvmppc_set_papr(PowerPCCPU *cpu);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
int kvmppc_smt_threads(void); int kvmppc_smt_threads(void);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
...@@ -81,6 +82,10 @@ static inline void kvmppc_set_papr(PowerPCCPU *cpu) ...@@ -81,6 +82,10 @@ static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{ {
} }
static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
}
static inline int kvmppc_smt_threads(void) static inline int kvmppc_smt_threads(void)
{ {
return 1; return 1;
......
...@@ -8633,9 +8633,9 @@ static const ppc_def_t ppc_defs[] = { ...@@ -8633,9 +8633,9 @@ static const ppc_def_t ppc_defs[] = {
POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2), POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2),
/* PowerPC e500v2 v3.0 core */ /* PowerPC e500v2 v3.0 core */
POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2), POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2),
POWERPC_DEF("e500mc", CPU_POWERPC_e500mc, e500mc), POWERPC_DEF_SVR("e500mc", CPU_POWERPC_e500mc, POWERPC_SVR_E500, e500mc),
#ifdef TARGET_PPC64 #ifdef TARGET_PPC64
POWERPC_DEF("e5500", CPU_POWERPC_e5500, e5500), POWERPC_DEF_SVR("e5500", CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500),
#endif #endif
/* PowerPC e500 microcontrollers */ /* PowerPC e500 microcontrollers */
/* MPC8533 */ /* MPC8533 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册