diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2013-01-19 09:56:41 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2013-01-19 09:56:41 +0000 |
commit | 75f0585f1718c575716021d11bfeb695129f785d (patch) | |
tree | bb1a9ea23af027b8c37ae4b1147f801d32c71ce1 | |
parent | 67c4f2d0e11de8ee534b17edafbcbcdcca4b0e9b (diff) | |
parent | 5b95b8b9c1b0cd30a31dbeffdaec35134248b6e9 (diff) |
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
-rw-r--r-- | hw/openpic.c | 40 | ||||
-rw-r--r-- | hw/ppc.c | 17 | ||||
-rw-r--r-- | hw/ppc.h | 2 | ||||
-rw-r--r-- | hw/ppc/e500.c | 17 | ||||
-rw-r--r-- | linux-headers/asm-powerpc/kvm.h | 6 | ||||
-rw-r--r-- | linux-headers/linux/kvm.h | 27 | ||||
-rw-r--r-- | target-ppc/kvm.c | 21 | ||||
-rw-r--r-- | target-ppc/kvm_ppc.h | 5 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 4 |
9 files changed, 115 insertions, 24 deletions
diff --git a/hw/openpic.c b/hw/openpic.c index f6cc07bd6e..cc8ec35b5d 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -40,6 +40,7 @@ #include "sysbus.h" #include "pci/msi.h" #include "qemu/bitops.h" +#include "ppc.h" //#define DEBUG_OPENPIC @@ -644,6 +645,26 @@ static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val) 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, unsigned len) { @@ -672,23 +693,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, case 0x1000: /* FRR */ break; case 0x1020: /* GCR */ - if (val & GCR_RESET) { - 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; - } - } + openpic_gcr_write(opp, val); break; case 0x1080: /* VIR */ break; @@ -1464,6 +1469,7 @@ static int openpic_init(SysBusDevice *dev) opp->irq_ipi0 = RAVEN_IPI_IRQ; opp->irq_tim0 = RAVEN_TMR_IRQ; opp->brr1 = -1; + opp->mpic_mode_mask = GCR_MODE_MIXED; list = list_le; /* Don't map MSI region */ list[2].map = false; @@ -428,6 +428,23 @@ void ppce500_irq_init(CPUPPCState *env) env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, 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 */ @@ -73,6 +73,8 @@ void ppc6xx_irq_init (CPUPPCState *env); void ppc970_irq_init (CPUPPCState *env); void ppcPOWER7_irq_init (CPUPPCState *env); +void ppce500_set_mpic_proxy(bool enabled); + /* PPC machines for OpenBIOS */ enum { ARCH_PREP = 0, diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 7b3e2e6723..c36821a99f 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -41,6 +41,7 @@ #define UIMAGE_LOAD_BASE 0 #define DTC_LOAD_PAD 0x1800000 #define DTC_PAD_MASK 0xFFFFF +#define DTB_MAX_SIZE (8 * 1024 * 1024) #define INITRD_LOAD_PAD 0x2000000 #define INITRD_PAD_MASK 0xFFFFFF @@ -463,7 +464,8 @@ void ppce500_init(PPCE500Params *params) target_long kernel_size=0; target_ulong dt_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; unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; qemu_irq **irqs, *mpic; @@ -626,12 +628,17 @@ void ppce500_init(PPCE500Params *params) params->kernel_filename); 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. */ if (params->initrd_filename) { - initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) & - ~INITRD_PAD_MASK; + initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; initrd_size = load_image_targphys(params->initrd_filename, initrd_base, ram_size - initrd_base); @@ -640,6 +647,8 @@ void ppce500_init(PPCE500Params *params) params->initrd_filename); exit(1); } + + cur_base = initrd_base + initrd_size; } /* If we're loading a kernel directly, we must load the device tree too. */ @@ -647,13 +656,13 @@ void ppce500_init(PPCE500Params *params) struct boot_info *boot_info; 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, initrd_size); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); exit(1); } + assert(dt_size < DTB_MAX_SIZE); boot_info = env->load_info; boot_info->entry = entry; diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h index 2fba8a66fb..16064d00ad 100644 --- a/linux-headers/asm-powerpc/kvm.h +++ b/linux-headers/asm-powerpc/kvm.h @@ -114,7 +114,10 @@ struct kvm_regs { /* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */ #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) /* External PID (E.PD) -- EPSC/EPLC */ @@ -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_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 */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index bfdbf4d1ad..5af935761c 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -168,6 +168,8 @@ struct kvm_pit_config { #define KVM_EXIT_PAPR_HCALL 19 #define KVM_EXIT_S390_UCONTROL 20 #define KVM_EXIT_WATCHDOG 21 +#define KVM_EXIT_S390_TSCH 22 +#define KVM_EXIT_EPR 23 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -285,6 +287,19 @@ struct kvm_run { __u64 ret; __u64 args[9]; } 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. */ char padding[256]; }; @@ -397,10 +412,20 @@ struct kvm_s390_psw { #define KVM_S390_PROGRAM_INT 0xfffe0001u #define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u #define KVM_S390_RESTART 0xfffe0003u +#define KVM_S390_MCHK 0xfffe1000u #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 +/* 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 { __u32 type; @@ -635,6 +660,8 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_IRQFD_RESAMPLE 82 #define KVM_CAP_PPC_BOOKE_WATCHDOG 83 #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 diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 19e9f25b19..2f4f06818a 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -846,6 +846,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = 0; break; #endif + case KVM_EXIT_EPR: + dprintf("handle epr\n"); + run->epr.epr = ldl_phys(env->mpic_iack); + ret = 0; + break; default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); ret = -1; @@ -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) { return cap_ppc_smt ? cap_ppc_smt : 1; diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 3db21fc889..c30b006674 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -25,6 +25,7 @@ int kvmppc_get_hasidle(CPUPPCState *env); int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len); int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level); void kvmppc_set_papr(PowerPCCPU *cpu); +void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy); int kvmppc_smt_threads(void); #ifndef CONFIG_USER_ONLY off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); @@ -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) { return 1; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 3f199c4bb9..2d78529273 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8633,9 +8633,9 @@ static const ppc_def_t ppc_defs[] = { POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2), /* PowerPC e500v2 v3.0 core */ 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 - POWERPC_DEF("e5500", CPU_POWERPC_e5500, e5500), + POWERPC_DEF_SVR("e5500", CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500), #endif /* PowerPC e500 microcontrollers */ /* MPC8533 */ |