Skip to content

Commit e0d79c9

Browse files
committed
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* VMX feature fix (myself) * HVF fixes (Cameron) # gpg: Signature made Tue 26 Nov 2019 08:58:43 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "[email protected]" # gpg: Good signature from "Paolo Bonzini <[email protected]>" [full] # gpg: aka "Paolo Bonzini <[email protected]>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: hvf: more accurately match SDM when setting CR0 and PDPTE registers hvf: correctly handle REX prefix in relation to legacy prefixes hvf: remove TSC synchronization code because it isn't fully complete hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in target/i386: add two missing VMX features for Skylake and CascadeLake Server Signed-off-by: Peter Maydell <[email protected]>
2 parents 5f64adc + e37aa8b commit e0d79c9

File tree

7 files changed

+104
-72
lines changed

7 files changed

+104
-72
lines changed

target/i386/cpu.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -3006,7 +3006,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
30063006
VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT |
30073007
VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
30083008
VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID |
3009-
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS,
3009+
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS |
3010+
VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML,
30103011
.xlevel = 0x80000008,
30113012
.model_id = "Intel Xeon Processor (Skylake)",
30123013
.versions = (X86CPUVersionDefinition[]) {
@@ -3131,7 +3132,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
31313132
VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT |
31323133
VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
31333134
VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID |
3134-
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS,
3135+
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS |
3136+
VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML,
31353137
.xlevel = 0x80000008,
31363138
.model_id = "Intel Xeon Processor (Cascadelake)",
31373139
.versions = (X86CPUVersionDefinition[]) {

target/i386/hvf/hvf.c

+44-17
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@ static void assert_hvf_ok(hv_return_t ret)
107107
}
108108

109109
/* Memory slots */
110-
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t end)
110+
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
111111
{
112112
hvf_slot *slot;
113113
int x;
114114
for (x = 0; x < hvf_state->num_slots; ++x) {
115115
slot = &hvf_state->slots[x];
116116
if (slot->size && start < (slot->start + slot->size) &&
117-
end > slot->start) {
117+
(start + size) > slot->start) {
118118
return slot;
119119
}
120120
}
@@ -129,12 +129,10 @@ struct mac_slot {
129129
};
130130

131131
struct mac_slot mac_slots[32];
132-
#define ALIGN(x, y) (((x) + (y) - 1) & ~((y) - 1))
133132

134-
static int do_hvf_set_memory(hvf_slot *slot)
133+
static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
135134
{
136135
struct mac_slot *macslot;
137-
hv_memory_flags_t flags;
138136
hv_return_t ret;
139137

140138
macslot = &mac_slots[slot->slot_id];
@@ -151,8 +149,6 @@ static int do_hvf_set_memory(hvf_slot *slot)
151149
return 0;
152150
}
153151

154-
flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
155-
156152
macslot->present = 1;
157153
macslot->gpa_start = slot->start;
158154
macslot->size = slot->size;
@@ -165,14 +161,24 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
165161
{
166162
hvf_slot *mem;
167163
MemoryRegion *area = section->mr;
164+
bool writeable = !area->readonly && !area->rom_device;
165+
hv_memory_flags_t flags;
168166

169167
if (!memory_region_is_ram(area)) {
170-
return;
168+
if (writeable) {
169+
return;
170+
} else if (!memory_region_is_romd(area)) {
171+
/*
172+
* If the memory device is not in romd_mode, then we actually want
173+
* to remove the hvf memory slot so all accesses will trap.
174+
*/
175+
add = false;
176+
}
171177
}
172178

173179
mem = hvf_find_overlap_slot(
174180
section->offset_within_address_space,
175-
section->offset_within_address_space + int128_get64(section->size));
181+
int128_get64(section->size));
176182

177183
if (mem && add) {
178184
if (mem->size == int128_get64(section->size) &&
@@ -186,7 +192,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
186192
/* Region needs to be reset. set the size to 0 and remap it. */
187193
if (mem) {
188194
mem->size = 0;
189-
if (do_hvf_set_memory(mem)) {
195+
if (do_hvf_set_memory(mem, 0)) {
190196
error_report("Failed to reset overlapping slot");
191197
abort();
192198
}
@@ -196,6 +202,13 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
196202
return;
197203
}
198204

205+
if (area->readonly ||
206+
(!memory_region_is_ram(area) && memory_region_is_romd(area))) {
207+
flags = HV_MEMORY_READ | HV_MEMORY_EXEC;
208+
} else {
209+
flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
210+
}
211+
199212
/* Now make a new slot. */
200213
int x;
201214

@@ -216,7 +229,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
216229
mem->start = section->offset_within_address_space;
217230
mem->region = area;
218231

219-
if (do_hvf_set_memory(mem)) {
232+
if (do_hvf_set_memory(mem, flags)) {
220233
error_report("Error registering new memory slot");
221234
abort();
222235
}
@@ -345,7 +358,14 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
345358
return false;
346359
}
347360

348-
return !slot;
361+
if (!slot) {
362+
return true;
363+
}
364+
if (!memory_region_is_ram(slot->region) &&
365+
!(read && memory_region_is_romd(slot->region))) {
366+
return true;
367+
}
368+
return false;
349369
}
350370

351371
static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
@@ -354,7 +374,7 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
354374

355375
slot = hvf_find_overlap_slot(
356376
section->offset_within_address_space,
357-
section->offset_within_address_space + int128_get64(section->size));
377+
int128_get64(section->size));
358378

359379
/* protect region against writes; begin tracking it */
360380
if (on) {
@@ -421,12 +441,20 @@ static MemoryListener hvf_memory_listener = {
421441
};
422442

423443
void hvf_reset_vcpu(CPUState *cpu) {
444+
uint64_t pdpte[4] = {0, 0, 0, 0};
445+
int i;
424446

425447
/* TODO: this shouldn't be needed; there is already a call to
426448
* cpu_synchronize_all_post_reset in vl.c
427449
*/
428450
wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, 0);
429451
wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, 0);
452+
453+
/* Initialize PDPTE */
454+
for (i = 0; i < 4; i++) {
455+
wvmcs(cpu->hvf_fd, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
456+
}
457+
430458
macvm_set_cr0(cpu->hvf_fd, 0x60000010);
431459

432460
wvmcs(cpu->hvf_fd, VMCS_CR4_MASK, CR4_VMXE_MASK);
@@ -498,7 +526,6 @@ void hvf_reset_vcpu(CPUState *cpu) {
498526
wreg(cpu->hvf_fd, HV_X86_R8 + i, 0x0);
499527
}
500528

501-
hv_vm_sync_tsc(0);
502529
hv_vcpu_invalidate_tlb(cpu->hvf_fd);
503530
hv_vcpu_flush(cpu->hvf_fd);
504531
}
@@ -592,7 +619,7 @@ int hvf_init_vcpu(CPUState *cpu)
592619
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_GSBASE, 1);
593620
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_KERNELGSBASE, 1);
594621
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_TSC_AUX, 1);
595-
/*hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);*/
622+
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);
596623
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_CS, 1);
597624
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_EIP, 1);
598625
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_ESP, 1);
@@ -720,7 +747,7 @@ int hvf_vcpu_exec(CPUState *cpu)
720747
ret = EXCP_INTERRUPT;
721748
break;
722749
}
723-
/* Need to check if MMIO or unmmaped fault */
750+
/* Need to check if MMIO or unmapped fault */
724751
case EXIT_REASON_EPT_FAULT:
725752
{
726753
hvf_slot *slot;
@@ -731,7 +758,7 @@ int hvf_vcpu_exec(CPUState *cpu)
731758
vmx_set_nmi_blocking(cpu);
732759
}
733760

734-
slot = hvf_find_overlap_slot(gpa, gpa);
761+
slot = hvf_find_overlap_slot(gpa, 1);
735762
/* mmio */
736763
if (ept_emulation_fault(slot, gpa, exit_qual)) {
737764
struct x86_decode decode;

target/i386/hvf/vmx.h

+10-8
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,23 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
121121
uint64_t pdpte[4] = {0, 0, 0, 0};
122122
uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER);
123123
uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0);
124+
uint64_t mask = CR0_PG | CR0_CD | CR0_NW | CR0_NE | CR0_ET;
124125

125126
if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) &&
126127
!(efer & MSR_EFER_LME)) {
127128
address_space_rw(&address_space_memory,
128129
rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f,
129130
MEMTXATTRS_UNSPECIFIED,
130131
(uint8_t *)pdpte, 32, 0);
132+
/* Only set PDPTE when appropriate. */
133+
for (i = 0; i < 4; i++) {
134+
wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
135+
}
131136
}
132137

133-
for (i = 0; i < 4; i++) {
134-
wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
135-
}
136-
137-
wvmcs(vcpu, VMCS_CR0_MASK, CR0_CD | CR0_NE | CR0_PG);
138+
wvmcs(vcpu, VMCS_CR0_MASK, mask);
138139
wvmcs(vcpu, VMCS_CR0_SHADOW, cr0);
139140

140-
cr0 &= ~CR0_CD;
141-
wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET);
142-
143141
if (efer & MSR_EFER_LME) {
144142
if (!(old_cr0 & CR0_PG) && (cr0 & CR0_PG)) {
145143
enter_long_mode(vcpu, cr0, efer);
@@ -149,6 +147,10 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
149147
}
150148
}
151149

150+
/* Filter new CR0 after we are finished examining it above. */
151+
cr0 = (cr0 & ~(mask & ~CR0_PG));
152+
wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET);
153+
152154
hv_vcpu_invalidate_tlb(vcpu);
153155
hv_vcpu_flush(vcpu);
154156
}

target/i386/hvf/x86_decode.c

+36-28
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ static void decode_rax(CPUX86State *env, struct x86_decode *decode,
122122
{
123123
op->type = X86_VAR_REG;
124124
op->reg = R_EAX;
125-
op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, 0,
125+
/* Since reg is always AX, REX prefix has no impact. */
126+
op->ptr = get_reg_ref(env, op->reg, false, 0,
126127
decode->operand_size);
127128
}
128129

@@ -1687,40 +1688,37 @@ void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
16871688
}
16881689
}
16891690

1690-
target_ulong get_reg_ref(CPUX86State *env, int reg, int rex, int is_extended,
1691-
int size)
1691+
target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present,
1692+
int is_extended, int size)
16921693
{
16931694
target_ulong ptr = 0;
1694-
int which = 0;
16951695

16961696
if (is_extended) {
16971697
reg |= R_R8;
16981698
}
16991699

1700-
17011700
switch (size) {
17021701
case 1:
1703-
if (is_extended || reg < 4 || rex) {
1704-
which = 1;
1702+
if (is_extended || reg < 4 || rex_present) {
17051703
ptr = (target_ulong)&RL(env, reg);
17061704
} else {
1707-
which = 2;
17081705
ptr = (target_ulong)&RH(env, reg - 4);
17091706
}
17101707
break;
17111708
default:
1712-
which = 3;
17131709
ptr = (target_ulong)&RRX(env, reg);
17141710
break;
17151711
}
17161712
return ptr;
17171713
}
17181714

1719-
target_ulong get_reg_val(CPUX86State *env, int reg, int rex, int is_extended,
1720-
int size)
1715+
target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
1716+
int is_extended, int size)
17211717
{
17221718
target_ulong val = 0;
1723-
memcpy(&val, (void *)get_reg_ref(env, reg, rex, is_extended, size), size);
1719+
memcpy(&val,
1720+
(void *)get_reg_ref(env, reg, rex_present, is_extended, size),
1721+
size);
17241722
return val;
17251723
}
17261724

@@ -1853,28 +1851,38 @@ void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
18531851
static void decode_prefix(CPUX86State *env, struct x86_decode *decode)
18541852
{
18551853
while (1) {
1854+
/*
1855+
* REX prefix must come after legacy prefixes.
1856+
* REX before legacy is ignored.
1857+
* Clear rex to simulate this.
1858+
*/
18561859
uint8_t byte = decode_byte(env, decode);
18571860
switch (byte) {
18581861
case PREFIX_LOCK:
18591862
decode->lock = byte;
1863+
decode->rex.rex = 0;
18601864
break;
18611865
case PREFIX_REPN:
18621866
case PREFIX_REP:
18631867
decode->rep = byte;
1868+
decode->rex.rex = 0;
18641869
break;
1865-
case PREFIX_CS_SEG_OVEERIDE:
1866-
case PREFIX_SS_SEG_OVEERIDE:
1867-
case PREFIX_DS_SEG_OVEERIDE:
1868-
case PREFIX_ES_SEG_OVEERIDE:
1869-
case PREFIX_FS_SEG_OVEERIDE:
1870-
case PREFIX_GS_SEG_OVEERIDE:
1870+
case PREFIX_CS_SEG_OVERRIDE:
1871+
case PREFIX_SS_SEG_OVERRIDE:
1872+
case PREFIX_DS_SEG_OVERRIDE:
1873+
case PREFIX_ES_SEG_OVERRIDE:
1874+
case PREFIX_FS_SEG_OVERRIDE:
1875+
case PREFIX_GS_SEG_OVERRIDE:
18711876
decode->segment_override = byte;
1877+
decode->rex.rex = 0;
18721878
break;
18731879
case PREFIX_OP_SIZE_OVERRIDE:
18741880
decode->op_size_override = byte;
1881+
decode->rex.rex = 0;
18751882
break;
18761883
case PREFIX_ADDR_SIZE_OVERRIDE:
18771884
decode->addr_size_override = byte;
1885+
decode->rex.rex = 0;
18781886
break;
18791887
case PREFIX_REX ... (PREFIX_REX + 0xf):
18801888
if (x86_is_long_mode(env_cpu(env))) {
@@ -2111,14 +2119,14 @@ void init_decoder()
21112119
{
21122120
int i;
21132121

2114-
for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
2115-
memcpy(_decode_tbl1, &invl_inst, sizeof(invl_inst));
2122+
for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) {
2123+
memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst));
21162124
}
21172125
for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
2118-
memcpy(_decode_tbl2, &invl_inst, sizeof(invl_inst));
2126+
memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst));
21192127
}
21202128
for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) {
2121-
memcpy(_decode_tbl3, &invl_inst, sizeof(invl_inst_x87));
2129+
memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87));
21222130

21232131
}
21242132
for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) {
@@ -2167,22 +2175,22 @@ target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
21672175
target_ulong addr, X86Seg seg)
21682176
{
21692177
switch (decode->segment_override) {
2170-
case PREFIX_CS_SEG_OVEERIDE:
2178+
case PREFIX_CS_SEG_OVERRIDE:
21712179
seg = R_CS;
21722180
break;
2173-
case PREFIX_SS_SEG_OVEERIDE:
2181+
case PREFIX_SS_SEG_OVERRIDE:
21742182
seg = R_SS;
21752183
break;
2176-
case PREFIX_DS_SEG_OVEERIDE:
2184+
case PREFIX_DS_SEG_OVERRIDE:
21772185
seg = R_DS;
21782186
break;
2179-
case PREFIX_ES_SEG_OVEERIDE:
2187+
case PREFIX_ES_SEG_OVERRIDE:
21802188
seg = R_ES;
21812189
break;
2182-
case PREFIX_FS_SEG_OVEERIDE:
2190+
case PREFIX_FS_SEG_OVERRIDE:
21832191
seg = R_FS;
21842192
break;
2185-
case PREFIX_GS_SEG_OVEERIDE:
2193+
case PREFIX_GS_SEG_OVERRIDE:
21862194
seg = R_GS;
21872195
break;
21882196
default:

0 commit comments

Comments
 (0)