mirror of https://gitee.com/openkylin/linux.git
KVM: PPC: Move kvmppc_ld/st to common code
We have enough common infrastructure now to resolve GVA->GPA mappings at runtime. With this we can move our book3s specific helpers to load / store in guest virtual address space to common code as well. Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
7d15c06f1a
commit
35c4a7330d
|
@ -148,8 +148,8 @@ extern void kvmppc_mmu_hpte_sysexit(void);
|
||||||
extern int kvmppc_mmu_hv_init(void);
|
extern int kvmppc_mmu_hv_init(void);
|
||||||
extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc);
|
extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc);
|
||||||
|
|
||||||
|
/* XXX remove this export when load_last_inst() is generic */
|
||||||
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
|
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
|
||||||
extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
|
|
||||||
extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
|
extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
|
||||||
extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
|
extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
|
||||||
unsigned int vec);
|
unsigned int vec);
|
||||||
|
|
|
@ -111,15 +111,15 @@ struct kvm_vcpu_stat {
|
||||||
u32 halt_wakeup;
|
u32 halt_wakeup;
|
||||||
u32 dbell_exits;
|
u32 dbell_exits;
|
||||||
u32 gdbell_exits;
|
u32 gdbell_exits;
|
||||||
|
u32 ld;
|
||||||
|
u32 st;
|
||||||
#ifdef CONFIG_PPC_BOOK3S
|
#ifdef CONFIG_PPC_BOOK3S
|
||||||
u32 pf_storage;
|
u32 pf_storage;
|
||||||
u32 pf_instruc;
|
u32 pf_instruc;
|
||||||
u32 sp_storage;
|
u32 sp_storage;
|
||||||
u32 sp_instruc;
|
u32 sp_instruc;
|
||||||
u32 queue_intr;
|
u32 queue_intr;
|
||||||
u32 ld;
|
|
||||||
u32 ld_slow;
|
u32 ld_slow;
|
||||||
u32 st;
|
|
||||||
u32 st_slow;
|
u32 st_slow;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,6 +80,10 @@ extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
|
extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
|
||||||
enum instruction_type type, u32 *inst);
|
enum instruction_type type, u32 *inst);
|
||||||
|
|
||||||
|
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
bool data);
|
||||||
|
extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
bool data);
|
||||||
extern int kvmppc_emulate_instruction(struct kvm_run *run,
|
extern int kvmppc_emulate_instruction(struct kvm_run *run,
|
||||||
struct kvm_vcpu *vcpu);
|
struct kvm_vcpu *vcpu);
|
||||||
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
||||||
|
|
|
@ -410,87 +410,6 @@ int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hva_t kvmppc_bad_hva(void)
|
|
||||||
{
|
|
||||||
return PAGE_OFFSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
|
|
||||||
{
|
|
||||||
hva_t hpage;
|
|
||||||
|
|
||||||
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
|
||||||
if (kvm_is_error_hva(hpage))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
return hpage | (pte->raddr & ~PAGE_MASK);
|
|
||||||
err:
|
|
||||||
return kvmppc_bad_hva();
|
|
||||||
}
|
|
||||||
|
|
||||||
int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
|
||||||
bool data)
|
|
||||||
{
|
|
||||||
struct kvmppc_pte pte;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
vcpu->stat.st++;
|
|
||||||
|
|
||||||
r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
|
||||||
XLATE_WRITE, &pte);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
*eaddr = pte.raddr;
|
|
||||||
|
|
||||||
if (!pte.may_write)
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
|
|
||||||
return EMULATE_DO_MMIO;
|
|
||||||
|
|
||||||
return EMULATE_DONE;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kvmppc_st);
|
|
||||||
|
|
||||||
int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
|
||||||
bool data)
|
|
||||||
{
|
|
||||||
struct kvmppc_pte pte;
|
|
||||||
hva_t hva = *eaddr;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
vcpu->stat.ld++;
|
|
||||||
|
|
||||||
rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
|
||||||
XLATE_READ, &pte);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
*eaddr = pte.raddr;
|
|
||||||
|
|
||||||
if (!pte.may_read)
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
if (!data && !pte.may_execute)
|
|
||||||
return -ENOEXEC;
|
|
||||||
|
|
||||||
hva = kvmppc_pte_to_hva(vcpu, &pte);
|
|
||||||
if (kvm_is_error_hva(hva))
|
|
||||||
goto mmio;
|
|
||||||
|
|
||||||
if (copy_from_user(ptr, (void __user *)hva, size)) {
|
|
||||||
printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
|
|
||||||
goto mmio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EMULATE_DONE;
|
|
||||||
|
|
||||||
mmio:
|
|
||||||
return EMULATE_DO_MMIO;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kvmppc_ld);
|
|
||||||
|
|
||||||
int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
|
int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
|
||||||
u32 *inst)
|
u32 *inst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -309,6 +309,87 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio);
|
EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio);
|
||||||
|
|
||||||
|
static hva_t kvmppc_bad_hva(void)
|
||||||
|
{
|
||||||
|
return PAGE_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
|
||||||
|
{
|
||||||
|
hva_t hpage;
|
||||||
|
|
||||||
|
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
||||||
|
if (kvm_is_error_hva(hpage))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return hpage | (pte->raddr & ~PAGE_MASK);
|
||||||
|
err:
|
||||||
|
return kvmppc_bad_hva();
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
bool data)
|
||||||
|
{
|
||||||
|
struct kvmppc_pte pte;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
vcpu->stat.st++;
|
||||||
|
|
||||||
|
r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
||||||
|
XLATE_WRITE, &pte);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*eaddr = pte.raddr;
|
||||||
|
|
||||||
|
if (!pte.may_write)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
|
||||||
|
return EMULATE_DO_MMIO;
|
||||||
|
|
||||||
|
return EMULATE_DONE;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(kvmppc_st);
|
||||||
|
|
||||||
|
int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
bool data)
|
||||||
|
{
|
||||||
|
struct kvmppc_pte pte;
|
||||||
|
hva_t hva = *eaddr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
vcpu->stat.ld++;
|
||||||
|
|
||||||
|
rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
||||||
|
XLATE_READ, &pte);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*eaddr = pte.raddr;
|
||||||
|
|
||||||
|
if (!pte.may_read)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (!data && !pte.may_execute)
|
||||||
|
return -ENOEXEC;
|
||||||
|
|
||||||
|
hva = kvmppc_pte_to_hva(vcpu, &pte);
|
||||||
|
if (kvm_is_error_hva(hva))
|
||||||
|
goto mmio;
|
||||||
|
|
||||||
|
if (copy_from_user(ptr, (void __user *)hva, size)) {
|
||||||
|
printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
|
||||||
|
goto mmio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EMULATE_DONE;
|
||||||
|
|
||||||
|
mmio:
|
||||||
|
return EMULATE_DO_MMIO;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(kvmppc_ld);
|
||||||
|
|
||||||
int kvm_arch_hardware_enable(void *garbage)
|
int kvm_arch_hardware_enable(void *garbage)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue