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