diff options
author | Paul Mackerras <paulus@samba.org> | 2014-06-01 21:02:59 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-07-28 09:22:17 -0400 |
commit | 699a0ea0823d32030b0666b28ff8633960f7ffa7 (patch) | |
tree | fdfa3e767593f47b66a08313e97cd0fe35b12300 /arch/powerpc/kvm/book3s_hv.c | |
parent | 1f0eeb7e1a88f46afa0f435cf7c34b0c84cf2394 (diff) |
KVM: PPC: Book3S: Controls for in-kernel sPAPR hypercall handling
This provides a way for userspace controls which sPAPR hcalls get
handled in the kernel. Each hcall can be individually enabled or
disabled for in-kernel handling, except for H_RTAS. The exception
for H_RTAS is because userspace can already control whether
individual RTAS functions are handled in-kernel or not via the
KVM_PPC_RTAS_DEFINE_TOKEN ioctl, and because the numeric value for
H_RTAS is out of the normal sequence of hcall numbers.
Hcalls are enabled or disabled using the KVM_ENABLE_CAP ioctl for the
KVM_CAP_PPC_ENABLE_HCALL capability on the file descriptor for the VM.
The args field of the struct kvm_enable_cap specifies the hcall number
in args[0] and the enable/disable flag in args[1]; 0 means disable
in-kernel handling (so that the hcall will always cause an exit to
userspace) and 1 means enable. Enabling or disabling in-kernel
handling of an hcall is effective across the whole VM.
The ability for KVM_ENABLE_CAP to be used on a VM file descriptor
on PowerPC is new, added by this commit. The KVM_CAP_ENABLE_CAP_VM
capability advertises that this ability exists.
When a VM is created, an initial set of hcalls are enabled for
in-kernel handling. The set that is enabled is the set that have
an in-kernel implementation at this point. Any new hcall
implementations from this point onwards should not be added to the
default set without a good reason.
No distinction is made between real-mode and virtual-mode hcall
implementations; the one setting controls them both.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 1562acfa05bf..cf445d22570f 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -67,6 +67,8 @@ | |||
67 | /* Used as a "null" value for timebase values */ | 67 | /* Used as a "null" value for timebase values */ |
68 | #define TB_NIL (~(u64)0) | 68 | #define TB_NIL (~(u64)0) |
69 | 69 | ||
70 | static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); | ||
71 | |||
70 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); | 72 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
71 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); | 73 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
72 | 74 | ||
@@ -562,6 +564,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
562 | struct kvm_vcpu *tvcpu; | 564 | struct kvm_vcpu *tvcpu; |
563 | int idx, rc; | 565 | int idx, rc; |
564 | 566 | ||
567 | if (req <= MAX_HCALL_OPCODE && | ||
568 | !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls)) | ||
569 | return RESUME_HOST; | ||
570 | |||
565 | switch (req) { | 571 | switch (req) { |
566 | case H_ENTER: | 572 | case H_ENTER: |
567 | idx = srcu_read_lock(&vcpu->kvm->srcu); | 573 | idx = srcu_read_lock(&vcpu->kvm->srcu); |
@@ -2269,6 +2275,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) | |||
2269 | */ | 2275 | */ |
2270 | cpumask_setall(&kvm->arch.need_tlb_flush); | 2276 | cpumask_setall(&kvm->arch.need_tlb_flush); |
2271 | 2277 | ||
2278 | /* Start out with the default set of hcalls enabled */ | ||
2279 | memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls, | ||
2280 | sizeof(kvm->arch.enabled_hcalls)); | ||
2281 | |||
2272 | kvm->arch.rma = NULL; | 2282 | kvm->arch.rma = NULL; |
2273 | 2283 | ||
2274 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); | 2284 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); |
@@ -2407,6 +2417,45 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp, | |||
2407 | return r; | 2417 | return r; |
2408 | } | 2418 | } |
2409 | 2419 | ||
2420 | /* | ||
2421 | * List of hcall numbers to enable by default. | ||
2422 | * For compatibility with old userspace, we enable by default | ||
2423 | * all hcalls that were implemented before the hcall-enabling | ||
2424 | * facility was added. Note this list should not include H_RTAS. | ||
2425 | */ | ||
2426 | static unsigned int default_hcall_list[] = { | ||
2427 | H_REMOVE, | ||
2428 | H_ENTER, | ||
2429 | H_READ, | ||
2430 | H_PROTECT, | ||
2431 | H_BULK_REMOVE, | ||
2432 | H_GET_TCE, | ||
2433 | H_PUT_TCE, | ||
2434 | H_SET_DABR, | ||
2435 | H_SET_XDABR, | ||
2436 | H_CEDE, | ||
2437 | H_PROD, | ||
2438 | H_CONFER, | ||
2439 | H_REGISTER_VPA, | ||
2440 | #ifdef CONFIG_KVM_XICS | ||
2441 | H_EOI, | ||
2442 | H_CPPR, | ||
2443 | H_IPI, | ||
2444 | H_IPOLL, | ||
2445 | H_XIRR, | ||
2446 | H_XIRR_X, | ||
2447 | #endif | ||
2448 | 0 | ||
2449 | }; | ||
2450 | |||
2451 | static void init_default_hcalls(void) | ||
2452 | { | ||
2453 | int i; | ||
2454 | |||
2455 | for (i = 0; default_hcall_list[i]; ++i) | ||
2456 | __set_bit(default_hcall_list[i] / 4, default_enabled_hcalls); | ||
2457 | } | ||
2458 | |||
2410 | static struct kvmppc_ops kvm_ops_hv = { | 2459 | static struct kvmppc_ops kvm_ops_hv = { |
2411 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, | 2460 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, |
2412 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, | 2461 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, |
@@ -2454,6 +2503,8 @@ static int kvmppc_book3s_init_hv(void) | |||
2454 | kvm_ops_hv.owner = THIS_MODULE; | 2503 | kvm_ops_hv.owner = THIS_MODULE; |
2455 | kvmppc_hv_ops = &kvm_ops_hv; | 2504 | kvmppc_hv_ops = &kvm_ops_hv; |
2456 | 2505 | ||
2506 | init_default_hcalls(); | ||
2507 | |||
2457 | r = kvmppc_mmu_hv_init(); | 2508 | r = kvmppc_mmu_hv_init(); |
2458 | return r; | 2509 | return r; |
2459 | } | 2510 | } |