mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 08:43:55 -06:00
Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf: (35 commits) PPC: KVM: Fix BAT put PPC: e500: Only expose even TLB sizes in initial TLB ppc/pseries: Reset VPA registration on CPU reset pseries: Don't test for MSR_PR for hypercalls under KVM PPC: e500: calculate initrd_base like dt_base PPC: e500: increase DTC_LOAD_PAD device tree: simplify dumpdtb code fdt: move dumpdtb interpretation code to device_tree.c target-ppc: Remove unused power_mode field from cpu state pseries: Set hash table size based on RAM size pseries: Remove unnecessary locking from PAPR hash table hcalls ppc405_uc: Fix buffer overflow target-ppc: KVM: Fix some kernel version edge cases for kvmppc_reset_htab() pseries: Fix semantics of RTAS int-on, int-off and set-xive functions pseries: Rework implementation of TCE bypass pseries: Remove never used flags field from spapr vio devices pseries: Remove XICS irq type enum type pseries: Remove C bitfields from xics code pseries: Small cleanup to H_CEDE implementation pseries: Fix XICS reset ...
This commit is contained in:
commit
6b2f90fbbd
21 changed files with 576 additions and 437 deletions
139
target-ppc/kvm.c
139
target-ppc/kvm.c
|
@ -60,6 +60,7 @@ static int cap_booke_sregs;
|
|||
static int cap_ppc_smt;
|
||||
static int cap_ppc_rma;
|
||||
static int cap_spapr_tce;
|
||||
static int cap_hior;
|
||||
|
||||
/* XXX We have a race condition where we actually have a level triggered
|
||||
* interrupt, but the infrastructure can't expose that yet, so the guest
|
||||
|
@ -86,6 +87,7 @@ int kvm_arch_init(KVMState *s)
|
|||
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
|
||||
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
|
||||
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
|
||||
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
|
||||
|
||||
if (!cap_interrupt_level) {
|
||||
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
|
||||
|
@ -469,6 +471,54 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
|
|||
env->tlb_dirty = false;
|
||||
}
|
||||
|
||||
if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) {
|
||||
struct kvm_sregs sregs;
|
||||
|
||||
sregs.pvr = env->spr[SPR_PVR];
|
||||
|
||||
sregs.u.s.sdr1 = env->spr[SPR_SDR1];
|
||||
|
||||
/* Sync SLB */
|
||||
#ifdef TARGET_PPC64
|
||||
for (i = 0; i < 64; i++) {
|
||||
sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid;
|
||||
sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sync SRs */
|
||||
for (i = 0; i < 16; i++) {
|
||||
sregs.u.s.ppc32.sr[i] = env->sr[i];
|
||||
}
|
||||
|
||||
/* Sync BATs */
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* Beware. We have to swap upper and lower bits here */
|
||||
sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32)
|
||||
| env->DBAT[1][i];
|
||||
sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32)
|
||||
| env->IBAT[1][i];
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (cap_hior && (level >= KVM_PUT_RESET_STATE)) {
|
||||
uint64_t hior = env->spr[SPR_HIOR];
|
||||
struct kvm_one_reg reg = {
|
||||
.id = KVM_REG_PPC_HIOR,
|
||||
.addr = (uintptr_t) &hior,
|
||||
};
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -946,52 +996,14 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
|||
void kvmppc_set_papr(CPUPPCState *env)
|
||||
{
|
||||
struct kvm_enable_cap cap = {};
|
||||
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);
|
||||
|
||||
if (ret) {
|
||||
goto fail;
|
||||
cpu_abort(env, "This KVM version does not support PAPR\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX We set HIOR here. It really should be a qdev property of
|
||||
* the CPU node, but we don't have CPUs converted to qdev yet.
|
||||
*
|
||||
* Once we have qdev CPUs, move HIOR to a qdev property and
|
||||
* remove this chunk.
|
||||
*/
|
||||
reg.id = KVM_REG_PPC_HIOR;
|
||||
reg.addr = (uintptr_t)&hior;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®);
|
||||
if (ret) {
|
||||
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 */
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
|
||||
if (ret) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sregs.u.s.sdr1 = env->spr[SPR_SDR1];
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
|
||||
if (ret) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
cpu_abort(env, "This KVM version does not support PAPR\n");
|
||||
}
|
||||
|
||||
int kvmppc_smt_threads(void)
|
||||
|
@ -999,6 +1011,7 @@ int kvmppc_smt_threads(void)
|
|||
return cap_ppc_smt ? cap_ppc_smt : 1;
|
||||
}
|
||||
|
||||
#ifdef TARGET_PPC64
|
||||
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
|
||||
{
|
||||
void *rma;
|
||||
|
@ -1042,6 +1055,16 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
|
|||
return size;
|
||||
}
|
||||
|
||||
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
|
||||
{
|
||||
if (cap_ppc_rma >= 2) {
|
||||
return current_size;
|
||||
}
|
||||
return MIN(current_size,
|
||||
getrampagesize() << (hash_shift - 7));
|
||||
}
|
||||
#endif
|
||||
|
||||
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
|
||||
{
|
||||
struct kvm_create_spapr_tce args = {
|
||||
|
@ -1101,6 +1124,44 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvmppc_reset_htab(int shift_hint)
|
||||
{
|
||||
uint32_t shift = shift_hint;
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
/* Full emulation, tell caller to allocate htab itself */
|
||||
return 0;
|
||||
}
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
|
||||
int ret;
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
|
||||
if (ret == -ENOTTY) {
|
||||
/* At least some versions of PR KVM advertise the
|
||||
* capability, but don't implement the ioctl(). Oops.
|
||||
* Return 0 so that we allocate the htab in qemu, as is
|
||||
* correct for PR. */
|
||||
return 0;
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
/* We have a kernel that predates the htab reset calls. For PR
|
||||
* KVM, we need to allocate the htab ourselves, for an HV KVM of
|
||||
* this era, it has allocated a 16MB fixed size hash table
|
||||
* already. Kernels of this era have the GET_PVINFO capability
|
||||
* only on PR, so we use this hack to determine the right
|
||||
* answer */
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
|
||||
/* PR - tell caller to allocate htab */
|
||||
return 0;
|
||||
} else {
|
||||
/* HV - assume 16MB kernel allocated htab */
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t mfpvr(void)
|
||||
{
|
||||
uint32_t pvr;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue