xref: /kvm-unit-tests/lib/s390x/hardware.c (revision d1e2a8e2d0d5856f1a6ce23ea3f044a1532eab40)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Functions to retrieve information about the host system.
4  *
5  * Copyright (c) 2020 Red Hat Inc
6  * Copyright 2022 IBM Corp.
7  *
8  * Authors:
9  *  Thomas Huth <thuth@redhat.com>
10  *  Claudio Imbrenda <imbrenda@linux.ibm.com>
11  */
12 
13 #include <libcflat.h>
14 #include <alloc_page.h>
15 #include <asm/arch_def.h>
16 #include <asm/page.h>
17 #include "hardware.h"
18 #include "stsi.h"
19 
20 /* The string "QEMU" in EBCDIC */
21 static const uint8_t qemu_ebcdic[] = { 0xd8, 0xc5, 0xd4, 0xe4 };
22 /* The string "KVM/" in EBCDIC */
23 static const uint8_t kvm_ebcdic[] = { 0xd2, 0xe5, 0xd4, 0x61 };
24 
do_detect_host(void)25 static enum s390_host do_detect_host(void)
26 {
27 	uint8_t buf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
28 	struct sysinfo_3_2_2 *stsi_322 = (struct sysinfo_3_2_2 *)buf;
29 
30 	if (stsi_get_fc() == 2)
31 		return HOST_IS_LPAR;
32 
33 	if (stsi_get_fc() != 3)
34 		return HOST_IS_UNKNOWN;
35 
36 	if (!stsi(buf, 1, 1, 1)) {
37 		/*
38 		 * If the manufacturer string is "QEMU" in EBCDIC, then we
39 		 * are on TCG (otherwise the string is "IBM" in EBCDIC)
40 		 */
41 		if (!memcmp((char *)buf + 32, qemu_ebcdic, sizeof(qemu_ebcdic)))
42 			return HOST_IS_TCG;
43 	}
44 
45 	if (!stsi(buf, 3, 2, 2)) {
46 		/*
47 		 * If the manufacturer string is "KVM/" in EBCDIC, then we
48 		 * are on KVM.
49 		 */
50 		if (!memcmp(&stsi_322->vm[0].cpi, kvm_ebcdic, sizeof(kvm_ebcdic)))
51 			return HOST_IS_KVM;
52 	}
53 
54 	return HOST_IS_UNKNOWN;
55 }
56 
detect_host(void)57 enum s390_host detect_host(void)
58 {
59 	static enum s390_host host = HOST_IS_UNKNOWN;
60 	static bool initialized = false;
61 
62 	if (initialized)
63 		return host;
64 
65 	host = do_detect_host();
66 	initialized = true;
67 	return host;
68 }
69