1 // SPDX-License-Identifier: GPL-2.0-only
2 #include "linux/types.h"
3 #include "linux/bitmap.h"
4 #include "linux/atomic.h"
7 #include "ucall_common.h"
10 #define GUEST_UCALL_FAILED -1
13 DECLARE_BITMAP(in_use
, KVM_MAX_VCPUS
);
14 struct ucall ucalls
[KVM_MAX_VCPUS
];
17 int ucall_nr_pages_required(uint64_t page_size
)
19 return align_up(sizeof(struct ucall_header
), page_size
) / page_size
;
23 * ucall_pool holds per-VM values (global data is duplicated by each VM), it
24 * must not be accessed from host code.
26 static struct ucall_header
*ucall_pool
;
28 void ucall_init(struct kvm_vm
*vm
, vm_paddr_t mmio_gpa
)
30 struct ucall_header
*hdr
;
35 vaddr
= vm_vaddr_alloc_shared(vm
, sizeof(*hdr
), KVM_UTIL_MIN_VADDR
,
37 hdr
= (struct ucall_header
*)addr_gva2hva(vm
, vaddr
);
38 memset(hdr
, 0, sizeof(*hdr
));
40 for (i
= 0; i
< KVM_MAX_VCPUS
; ++i
) {
45 write_guest_global(vm
, ucall_pool
, (struct ucall_header
*)vaddr
);
47 ucall_arch_init(vm
, mmio_gpa
);
50 static struct ucall
*ucall_alloc(void)
58 for (i
= 0; i
< KVM_MAX_VCPUS
; ++i
) {
59 if (!test_and_set_bit(i
, ucall_pool
->in_use
)) {
60 uc
= &ucall_pool
->ucalls
[i
];
61 memset(uc
->args
, 0, sizeof(uc
->args
));
68 * If the vCPU cannot grab a ucall structure, make a bare ucall with a
69 * magic value to signal to get_ucall() that things went sideways.
70 * GUEST_ASSERT() depends on ucall_alloc() and so cannot be used here.
72 ucall_arch_do_ucall(GUEST_UCALL_FAILED
);
76 static void ucall_free(struct ucall
*uc
)
78 /* Beware, here be pointer arithmetic. */
79 clear_bit(uc
- ucall_pool
->ucalls
, ucall_pool
->in_use
);
82 void ucall_assert(uint64_t cmd
, const char *exp
, const char *file
,
83 unsigned int line
, const char *fmt
, ...)
91 WRITE_ONCE(uc
->args
[GUEST_ERROR_STRING
], (uint64_t)(exp
));
92 WRITE_ONCE(uc
->args
[GUEST_FILE
], (uint64_t)(file
));
93 WRITE_ONCE(uc
->args
[GUEST_LINE
], line
);
96 guest_vsnprintf(uc
->buffer
, UCALL_BUFFER_LEN
, fmt
, va
);
99 ucall_arch_do_ucall((vm_vaddr_t
)uc
->hva
);
104 void ucall_fmt(uint64_t cmd
, const char *fmt
, ...)
113 guest_vsnprintf(uc
->buffer
, UCALL_BUFFER_LEN
, fmt
, va
);
116 ucall_arch_do_ucall((vm_vaddr_t
)uc
->hva
);
121 void ucall(uint64_t cmd
, int nargs
, ...)
129 WRITE_ONCE(uc
->cmd
, cmd
);
131 nargs
= min(nargs
, UCALL_MAX_ARGS
);
134 for (i
= 0; i
< nargs
; ++i
)
135 WRITE_ONCE(uc
->args
[i
], va_arg(va
, uint64_t));
138 ucall_arch_do_ucall((vm_vaddr_t
)uc
->hva
);
143 uint64_t get_ucall(struct kvm_vcpu
*vcpu
, struct ucall
*uc
)
151 addr
= ucall_arch_get_ucall(vcpu
);
153 TEST_ASSERT(addr
!= (void *)GUEST_UCALL_FAILED
,
154 "Guest failed to allocate ucall struct");
156 memcpy(uc
, addr
, sizeof(*uc
));
157 vcpu_run_complete_io(vcpu
);
159 memset(uc
, 0, sizeof(*uc
));