@@ -312,3 +312,21 @@ This command is always allowed.
* -KVM_ENOENT - the event specified by ``id`` is unsupported
* -KVM_EPERM - the event specified by ``id`` is disallowed
* -KVM_EINVAL - the padding is not zero
+
+4. KVMI_VM_GET_INFO
+-------------------
+
+:Architectures: all
+:Versions: >= 1
+:Parameters: none
+:Returns:
+
+::
+
+ struct kvmi_error_code;
+ struct kvmi_vm_get_info_reply {
+ __u32 vcpu_count;
+ __u32 padding[3];
+ };
+
+Returns the number of online vCPUs.
@@ -20,6 +20,7 @@ enum {
KVMI_GET_VERSION = KVMI_VM_MESSAGE_ID(1),
KVMI_VM_CHECK_COMMAND = KVMI_VM_MESSAGE_ID(2),
KVMI_VM_CHECK_EVENT = KVMI_VM_MESSAGE_ID(3),
+ KVMI_VM_GET_INFO = KVMI_VM_MESSAGE_ID(4),
KVMI_NEXT_VM_MESSAGE
};
@@ -67,4 +68,9 @@ struct kvmi_vm_check_event {
__u32 padding2;
};
+struct kvmi_vm_get_info_reply {
+ __u32 vcpu_count;
+ __u32 padding[3];
+};
+
#endif /* _UAPI__LINUX_KVMI_H */
@@ -80,6 +80,16 @@ static void set_command_perm(struct kvm_vm *vm, __s32 id, __u32 allow,
"KVM_INTROSPECTION_COMMAND");
}
+static void disallow_command(struct kvm_vm *vm, __s32 id)
+{
+ set_command_perm(vm, id, 0, 0);
+}
+
+static void allow_command(struct kvm_vm *vm, __s32 id)
+{
+ set_command_perm(vm, id, 1, 0);
+}
+
static void hook_introspection(struct kvm_vm *vm)
{
__u32 allow = 1, disallow = 0, allow_inval = 2;
@@ -256,12 +266,16 @@ static void cmd_vm_check_command(__u16 id, int expected_err)
expected_err);
}
-static void test_cmd_vm_check_command(void)
+static void test_cmd_vm_check_command(struct kvm_vm *vm)
{
- __u16 valid_id = KVMI_GET_VERSION, invalid_id = 0xffff;
+ __u16 valid_id = KVMI_VM_GET_INFO, invalid_id = 0xffff;
cmd_vm_check_command(valid_id, 0);
cmd_vm_check_command(invalid_id, -KVM_ENOENT);
+
+ disallow_command(vm, valid_id);
+ cmd_vm_check_command(valid_id, -KVM_EPERM);
+ allow_command(vm, valid_id);
}
static void cmd_vm_check_event(__u16 id, int expected_err)
@@ -284,6 +298,20 @@ static void test_cmd_vm_check_event(void)
cmd_vm_check_event(invalid_id, -KVM_ENOENT);
}
+static void test_cmd_vm_get_info(void)
+{
+ struct kvmi_vm_get_info_reply rpl;
+ struct kvmi_msg_hdr req;
+
+ test_vm_command(KVMI_VM_GET_INFO, &req, sizeof(req), &rpl,
+ sizeof(rpl), 0);
+ TEST_ASSERT(rpl.vcpu_count == 1,
+ "Unexpected number of vCPU count %u\n",
+ rpl.vcpu_count);
+
+ pr_debug("vcpu count: %u\n", rpl.vcpu_count);
+}
+
static void test_introspection(struct kvm_vm *vm)
{
setup_socket();
@@ -291,8 +319,9 @@ static void test_introspection(struct kvm_vm *vm)
test_cmd_invalid();
test_cmd_get_version();
- test_cmd_vm_check_command();
+ test_cmd_vm_check_command(vm);
test_cmd_vm_check_event();
+ test_cmd_vm_get_info();
unhook_introspection(vm);
}
@@ -150,6 +150,18 @@ static int handle_vm_check_event(struct kvm_introspection *kvmi,
return kvmi_msg_vm_reply(kvmi, msg, ec, NULL, 0);
}
+static int handle_vm_get_info(struct kvm_introspection *kvmi,
+ const struct kvmi_msg_hdr *msg,
+ const void *req)
+{
+ struct kvmi_vm_get_info_reply rpl;
+
+ memset(&rpl, 0, sizeof(rpl));
+ rpl.vcpu_count = atomic_read(&kvmi->kvm->online_vcpus);
+
+ return kvmi_msg_vm_reply(kvmi, msg, 0, &rpl, sizeof(rpl));
+}
+
/*
* These commands are executed by the receiving thread.
*/
@@ -157,6 +169,7 @@ static kvmi_vm_msg_fct const msg_vm[] = {
[KVMI_GET_VERSION] = handle_get_version,
[KVMI_VM_CHECK_COMMAND] = handle_vm_check_command,
[KVMI_VM_CHECK_EVENT] = handle_vm_check_event,
+ [KVMI_VM_GET_INFO] = handle_vm_get_info,
};
static kvmi_vm_msg_fct get_vm_msg_handler(u16 id)