Revision b827df58

b/kvm.h
120 120

  
121 121
int kvm_check_extension(KVMState *s, unsigned int extension);
122 122

  
123
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
124
                                      int reg);
125

  
123 126
/* generic hooks - to be moved/refactored once there are more users */
124 127

  
125 128
static inline void cpu_synchronize_state(CPUState *env, int modified)
b/target-i386/kvm.c
34 34
    do { } while (0)
35 35
#endif
36 36

  
37
#ifdef KVM_CAP_EXT_CPUID
38

  
39
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
40
{
41
    struct kvm_cpuid2 *cpuid;
42
    int r, size;
43

  
44
    size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
45
    cpuid = (struct kvm_cpuid2 *)qemu_mallocz(size);
46
    cpuid->nent = max;
47
    r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
48
    if (r < 0) {
49
        if (r == -E2BIG) {
50
            qemu_free(cpuid);
51
            return NULL;
52
        } else {
53
            fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
54
                    strerror(-r));
55
            exit(1);
56
        }
57
    }
58
    return cpuid;
59
}
60

  
61
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
62
{
63
    struct kvm_cpuid2 *cpuid;
64
    int i, max;
65
    uint32_t ret = 0;
66
    uint32_t cpuid_1_edx;
67

  
68
    if (!kvm_check_extension(env->kvm_state, KVM_CAP_EXT_CPUID)) {
69
        return -1U;
70
    }
71

  
72
    max = 1;
73
    while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
74
        max *= 2;
75
    }
76

  
77
    for (i = 0; i < cpuid->nent; ++i) {
78
        if (cpuid->entries[i].function == function) {
79
            switch (reg) {
80
            case R_EAX:
81
                ret = cpuid->entries[i].eax;
82
                break;
83
            case R_EBX:
84
                ret = cpuid->entries[i].ebx;
85
                break;
86
            case R_ECX:
87
                ret = cpuid->entries[i].ecx;
88
                break;
89
            case R_EDX:
90
                ret = cpuid->entries[i].edx;
91
                if (function == 0x80000001) {
92
                    /* On Intel, kvm returns cpuid according to the Intel spec,
93
                     * so add missing bits according to the AMD spec:
94
                     */
95
                    cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
96
                    ret |= cpuid_1_edx & 0xdfeff7ff;
97
                }
98
                break;
99
            }
100
        }
101
    }
102

  
103
    qemu_free(cpuid);
104

  
105
    return ret;
106
}
107

  
108
#else
109

  
110
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
111
{
112
    return -1U;
113
}
114

  
115
#endif
116

  
37 117
int kvm_arch_init_vcpu(CPUState *env)
38 118
{
39 119
    struct {

Also available in: Unified diff