aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/cpu_models.h
blob: cc7305ec2139ba075fa399f245d7cb50fb1b355f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * CPU models for s390x
 *
 * Copyright 2016 IBM Corp.
 *
 * Author(s): David Hildenbrand <dahi@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */

#ifndef TARGET_S390X_CPU_MODELS_H
#define TARGET_S390X_CPU_MODELS_H

#include "cpu_features.h"
#include "target/s390x/gen-features.h"
#include "hw/core/cpu.h"

/* static CPU definition */
struct S390CPUDef {
    const char *name;       /* name exposed to the user */
    const char *desc;       /* description exposed to the user */
    uint8_t gen;            /* hw generation identification */
    uint16_t type;          /* cpu type identification */
    uint8_t ec_ga;          /* EC GA version (on which also the BC is based) */
    uint8_t mha_pow;        /* maximum host address power, mha = 2^pow-1 */
    uint32_t hmfai;         /* hypervisor-managed facilities */
    /* base/min features, must never be changed between QEMU versions */
    S390FeatBitmap base_feat;
    /* used to init base_feat from generated data */
    S390FeatInit base_init;
    /* default features, QEMU version specific */
    S390FeatBitmap default_feat;
    /* used to init default_feat from generated data */
    S390FeatInit default_init;
    /* max allowed features, QEMU version specific */
    S390FeatBitmap full_feat;
    /* used to init full_feat from generated data */
    S390FeatInit full_init;
};

/* CPU model based on a CPU definition */
struct S390CPUModel {
    const S390CPUDef *def;
    S390FeatBitmap features;
    /* values copied from the "host" model, can change during migration */
    uint16_t lowest_ibc;    /* lowest IBC that the hardware supports */
    uint32_t cpu_id;        /* CPU id */
    uint8_t cpu_id_format;  /* CPU id format bit */
    uint8_t cpu_ver;        /* CPU version, usually "ff" for kvm */
};

/*
 * CPU ID
 *
 * bits 0-7: Zeroes (ff for kvm)
 * bits 8-31: CPU ID (serial number)
 * bits 32-47: Machine type
 * bit  48: CPU ID format
 * bits 49-63: Zeroes
 */
#define cpuid_type(x)     (((x) >> 16) & 0xffff)
#define cpuid_id(x)       (((x) >> 32) & 0xffffff)
#define cpuid_ver(x)      (((x) >> 56) & 0xff)
#define cpuid_format(x)   (((x) >> 15) & 0x1)

#define lowest_ibc(x)     (((uint32_t)(x) >> 16) & 0xfff)
#define unblocked_ibc(x)  ((uint32_t)(x) & 0xfff)
#define has_ibc(x)        (lowest_ibc(x) != 0)

#define S390_GEN_Z10 0xa
#define ibc_gen(x)        (x == 0 ? 0 : ((x >> 4) + S390_GEN_Z10))
#define ibc_ec_ga(x)      (x & 0xf)

void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat);
void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat);
void s390_cpudef_group_featoff_greater(uint8_t gen, uint8_t ec_ga,
                                       S390FeatGroup group);
uint32_t s390_get_hmfai(void);
uint8_t s390_get_mha_pow(void);
uint32_t s390_get_ibc_val(void);
static inline uint16_t s390_ibc_from_cpu_model(const S390CPUModel *model)
{
    uint16_t ibc = 0;

    if (model->def->gen >= S390_GEN_Z10) {
        ibc = ((model->def->gen - S390_GEN_Z10) << 4) + model->def->ec_ga;
    }
    return ibc;
}
void s390_get_feat_block(S390FeatType type, uint8_t *data);
bool s390_has_feat(S390Feat feat);
uint8_t s390_get_gen_for_cpu_type(uint16_t type);
static inline bool s390_known_cpu_type(uint16_t type)
{
    return s390_get_gen_for_cpu_type(type) != 0;
}
#define CPU_ID_SHIFT 32
#define CPU_ID_BITS 24
/*
 * When cpu_id_format is 0 (basic mode), the leftmost 4 bits of cpu_id contain
 * the rightmost 4 bits of the physical CPU address.
 */
#define CPU_PHYS_ADDR_BITS 4
#define CPU_PHYS_ADDR_SHIFT (CPU_ID_SHIFT + CPU_ID_BITS - CPU_PHYS_ADDR_BITS)
static inline uint64_t s390_cpuid_from_cpu_model(const S390CPUModel *model)
{
    return ((uint64_t)model->cpu_ver << 56) |
           ((uint64_t)model->cpu_id << CPU_ID_SHIFT) |
           ((uint64_t)model->def->type << 16) |
           (model->def->gen == 7 ? 0 : (uint64_t)model->cpu_id_format << 15);
}
S390CPUDef const *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga,
                                    S390FeatBitmap features);

#ifdef CONFIG_KVM
bool kvm_s390_cpu_models_supported(void);
void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp);
void kvm_s390_apply_cpu_model(const S390CPUModel *model,  Error **errp);
#else
static inline void kvm_s390_get_host_cpu_model(S390CPUModel *model,
                                               Error **errp)
{
}
static inline void kvm_s390_apply_cpu_model(const S390CPUModel *model,
                                            Error **errp)
{
}
static inline bool kvm_s390_cpu_models_supported(void)
{
    return false;
}
#endif

#endif /* TARGET_S390X_CPU_MODELS_H */