1*be76823fSMatt Evans /* 2*be76823fSMatt Evans * SPAPR hypercalls 3*be76823fSMatt Evans * 4*be76823fSMatt Evans * Borrowed heavily from QEMU's spapr_hcall.c, 5*be76823fSMatt Evans * Copyright (c) 2010 David Gibson, IBM Corporation. 6*be76823fSMatt Evans * 7*be76823fSMatt Evans * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation. 8*be76823fSMatt Evans * 9*be76823fSMatt Evans * This program is free software; you can redistribute it and/or modify it 10*be76823fSMatt Evans * under the terms of the GNU General Public License version 2 as published 11*be76823fSMatt Evans * by the Free Software Foundation. 12*be76823fSMatt Evans */ 13*be76823fSMatt Evans 14*be76823fSMatt Evans #include "spapr.h" 15*be76823fSMatt Evans #include "kvm/util.h" 16*be76823fSMatt Evans #include "kvm/kvm.h" 17*be76823fSMatt Evans #include "kvm/kvm-cpu.h" 18*be76823fSMatt Evans 19*be76823fSMatt Evans #include <stdio.h> 20*be76823fSMatt Evans #include <assert.h> 21*be76823fSMatt Evans 22*be76823fSMatt Evans static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; 23*be76823fSMatt Evans static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - 24*be76823fSMatt Evans KVMPPC_HCALL_BASE + 1]; 25*be76823fSMatt Evans 26*be76823fSMatt Evans static target_ulong h_set_dabr(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 27*be76823fSMatt Evans { 28*be76823fSMatt Evans /* FIXME: Implement this for -PR. (-HV does this in kernel.) */ 29*be76823fSMatt Evans return H_HARDWARE; 30*be76823fSMatt Evans } 31*be76823fSMatt Evans 32*be76823fSMatt Evans static target_ulong h_rtas(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 33*be76823fSMatt Evans { 34*be76823fSMatt Evans target_ulong rtas_r3 = args[0]; 35*be76823fSMatt Evans /* 36*be76823fSMatt Evans * Pointer read from phys mem; these ptrs cannot be MMIO (!) so just 37*be76823fSMatt Evans * reference guest RAM directly. 38*be76823fSMatt Evans */ 39*be76823fSMatt Evans uint32_t token, nargs, nret; 40*be76823fSMatt Evans 41*be76823fSMatt Evans token = rtas_ld(vcpu->kvm, rtas_r3, 0); 42*be76823fSMatt Evans nargs = rtas_ld(vcpu->kvm, rtas_r3, 1); 43*be76823fSMatt Evans nret = rtas_ld(vcpu->kvm, rtas_r3, 2); 44*be76823fSMatt Evans 45*be76823fSMatt Evans return spapr_rtas_call(vcpu, token, nargs, rtas_r3 + 12, 46*be76823fSMatt Evans nret, rtas_r3 + 12 + 4*nargs); 47*be76823fSMatt Evans } 48*be76823fSMatt Evans 49*be76823fSMatt Evans static target_ulong h_logical_load(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 50*be76823fSMatt Evans { 51*be76823fSMatt Evans /* SLOF will require these, though kernel doesn't. */ 52*be76823fSMatt Evans die(__PRETTY_FUNCTION__); 53*be76823fSMatt Evans return H_PARAMETER; 54*be76823fSMatt Evans } 55*be76823fSMatt Evans 56*be76823fSMatt Evans static target_ulong h_logical_store(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 57*be76823fSMatt Evans { 58*be76823fSMatt Evans /* SLOF will require these, though kernel doesn't. */ 59*be76823fSMatt Evans die(__PRETTY_FUNCTION__); 60*be76823fSMatt Evans return H_PARAMETER; 61*be76823fSMatt Evans } 62*be76823fSMatt Evans 63*be76823fSMatt Evans static target_ulong h_logical_icbi(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 64*be76823fSMatt Evans { 65*be76823fSMatt Evans /* KVM will trap this in the kernel. Die if it misses. */ 66*be76823fSMatt Evans die(__PRETTY_FUNCTION__); 67*be76823fSMatt Evans return H_SUCCESS; 68*be76823fSMatt Evans } 69*be76823fSMatt Evans 70*be76823fSMatt Evans static target_ulong h_logical_dcbf(struct kvm_cpu *vcpu, target_ulong opcode, target_ulong *args) 71*be76823fSMatt Evans { 72*be76823fSMatt Evans /* KVM will trap this in the kernel. Die if it misses. */ 73*be76823fSMatt Evans die(__PRETTY_FUNCTION__); 74*be76823fSMatt Evans return H_SUCCESS; 75*be76823fSMatt Evans } 76*be76823fSMatt Evans 77*be76823fSMatt Evans void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) 78*be76823fSMatt Evans { 79*be76823fSMatt Evans spapr_hcall_fn *slot; 80*be76823fSMatt Evans 81*be76823fSMatt Evans if (opcode <= MAX_HCALL_OPCODE) { 82*be76823fSMatt Evans assert((opcode & 0x3) == 0); 83*be76823fSMatt Evans 84*be76823fSMatt Evans slot = &papr_hypercall_table[opcode / 4]; 85*be76823fSMatt Evans } else { 86*be76823fSMatt Evans assert((opcode >= KVMPPC_HCALL_BASE) && 87*be76823fSMatt Evans (opcode <= KVMPPC_HCALL_MAX)); 88*be76823fSMatt Evans 89*be76823fSMatt Evans slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE]; 90*be76823fSMatt Evans } 91*be76823fSMatt Evans 92*be76823fSMatt Evans assert(!(*slot) || (fn == *slot)); 93*be76823fSMatt Evans *slot = fn; 94*be76823fSMatt Evans } 95*be76823fSMatt Evans 96*be76823fSMatt Evans target_ulong spapr_hypercall(struct kvm_cpu *vcpu, target_ulong opcode, 97*be76823fSMatt Evans target_ulong *args) 98*be76823fSMatt Evans { 99*be76823fSMatt Evans if ((opcode <= MAX_HCALL_OPCODE) 100*be76823fSMatt Evans && ((opcode & 0x3) == 0)) { 101*be76823fSMatt Evans spapr_hcall_fn fn = papr_hypercall_table[opcode / 4]; 102*be76823fSMatt Evans 103*be76823fSMatt Evans if (fn) { 104*be76823fSMatt Evans return fn(vcpu, opcode, args); 105*be76823fSMatt Evans } 106*be76823fSMatt Evans } else if ((opcode >= KVMPPC_HCALL_BASE) && 107*be76823fSMatt Evans (opcode <= KVMPPC_HCALL_MAX)) { 108*be76823fSMatt Evans spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - 109*be76823fSMatt Evans KVMPPC_HCALL_BASE]; 110*be76823fSMatt Evans 111*be76823fSMatt Evans if (fn) { 112*be76823fSMatt Evans return fn(vcpu, opcode, args); 113*be76823fSMatt Evans } 114*be76823fSMatt Evans } 115*be76823fSMatt Evans 116*be76823fSMatt Evans hcall_dprintf("Unimplemented hcall 0x%lx\n", opcode); 117*be76823fSMatt Evans return H_FUNCTION; 118*be76823fSMatt Evans } 119*be76823fSMatt Evans 120*be76823fSMatt Evans void hypercall_init(void) 121*be76823fSMatt Evans { 122*be76823fSMatt Evans /* hcall-dabr */ 123*be76823fSMatt Evans spapr_register_hypercall(H_SET_DABR, h_set_dabr); 124*be76823fSMatt Evans 125*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load); 126*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store); 127*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load); 128*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store); 129*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi); 130*be76823fSMatt Evans spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf); 131*be76823fSMatt Evans 132*be76823fSMatt Evans /* KVM-PPC specific hcalls */ 133*be76823fSMatt Evans spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); 134*be76823fSMatt Evans } 135