xref: /kvmtool/powerpc/spapr_hcall.c (revision be76823f649b3b21bdc617812bcaa51e37a545ba)
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