mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 18:44:58 -06:00
* target/i386: Fix physical address truncation on 32-bit PAE
* Remove globals for options -no-fd-bootchk and -win2k-hack -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmXebwQUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPozAf/Vgc9u6C+8PcPDrol6qxjI+EOHLNy 7M3/OFpUkwLXuOSawb6syYxHpLS38fKRcsb2ninngUmbRWA6p+KNUizlAFMj7op5 wJmtdamCwCwXXaw20SfWxx2Ih0JS7FQsRsU94HTOdaDB17C9+hBcYwcggsOAXCmq gyVenEF1mov2A4jLMhdVIRX784AAoEP+QAuhBKQBrQwRLCTTyNdHl7jXdB9w+2sh KafokoFLcozJHz/tN3AhRKy6zjPugJyQmJwBRuj9tstCILtXpvf/ZE/3pUq5l3ZY A6dCI0zWAlGNTkpKRXsMFozNIVP2htnyidy29XHptlY5acfjtQ++rMu3BQ== =WY4H -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * target/i386: Fix physical address truncation on 32-bit PAE * Remove globals for options -no-fd-bootchk and -win2k-hack # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmXebwQUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroPozAf/Vgc9u6C+8PcPDrol6qxjI+EOHLNy # 7M3/OFpUkwLXuOSawb6syYxHpLS38fKRcsb2ninngUmbRWA6p+KNUizlAFMj7op5 # wJmtdamCwCwXXaw20SfWxx2Ih0JS7FQsRsU94HTOdaDB17C9+hBcYwcggsOAXCmq # gyVenEF1mov2A4jLMhdVIRX784AAoEP+QAuhBKQBrQwRLCTTyNdHl7jXdB9w+2sh # KafokoFLcozJHz/tN3AhRKy6zjPugJyQmJwBRuj9tstCILtXpvf/ZE/3pUq5l3ZY # A6dCI0zWAlGNTkpKRXsMFozNIVP2htnyidy29XHptlY5acfjtQ++rMu3BQ== # =WY4H # -----END PGP SIGNATURE----- # gpg: Signature made Tue 27 Feb 2024 23:23:48 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [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 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: ide, vl: turn -win2k-hack into a property on IDE devices ide: collapse parameters to ide_init_drive target/i386: leave the A20 bit set in the final NPT walk target/i386: remove unnecessary/wrong application of the A20 mask target/i386: Fix physical address truncation target/i386: use separate MMU indexes for 32-bit accesses target/i386: introduce function to query MMU indices target/i386: check validity of VMCB addresses target/i386: mask high bits of CR3 in 32-bit mode vl, pc: turn -no-fd-bootchk into a machine property Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
bfe8020c81
15 changed files with 157 additions and 90 deletions
|
@ -7735,10 +7735,13 @@ static bool x86_cpu_has_work(CPUState *cs)
|
|||
static int x86_cpu_mmu_index(CPUState *cs, bool ifetch)
|
||||
{
|
||||
CPUX86State *env = cpu_env(cs);
|
||||
int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 1 : 0;
|
||||
int mmu_index_base =
|
||||
(env->hflags & HF_CPL_MASK) == 3 ? MMU_USER64_IDX :
|
||||
!(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
|
||||
(env->eflags & AC_MASK) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
|
||||
|
||||
return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
|
||||
(!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
|
||||
? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
|
||||
return mmu_index_base + mmu_index_32;
|
||||
}
|
||||
|
||||
static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
|
||||
|
|
|
@ -2299,17 +2299,47 @@ uint64_t cpu_get_tsc(CPUX86State *env);
|
|||
#define cpu_list x86_cpu_list
|
||||
|
||||
/* MMU modes definitions */
|
||||
#define MMU_KSMAP_IDX 0
|
||||
#define MMU_USER_IDX 1
|
||||
#define MMU_KNOSMAP_IDX 2
|
||||
#define MMU_NESTED_IDX 3
|
||||
#define MMU_PHYS_IDX 4
|
||||
#define MMU_KSMAP64_IDX 0
|
||||
#define MMU_KSMAP32_IDX 1
|
||||
#define MMU_USER64_IDX 2
|
||||
#define MMU_USER32_IDX 3
|
||||
#define MMU_KNOSMAP64_IDX 4
|
||||
#define MMU_KNOSMAP32_IDX 5
|
||||
#define MMU_PHYS_IDX 6
|
||||
#define MMU_NESTED_IDX 7
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#ifdef TARGET_X86_64
|
||||
#define MMU_USER_IDX MMU_USER64_IDX
|
||||
#else
|
||||
#define MMU_USER_IDX MMU_USER32_IDX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline bool is_mmu_index_smap(int mmu_index)
|
||||
{
|
||||
return (mmu_index & ~1) == MMU_KSMAP64_IDX;
|
||||
}
|
||||
|
||||
static inline bool is_mmu_index_user(int mmu_index)
|
||||
{
|
||||
return (mmu_index & ~1) == MMU_USER64_IDX;
|
||||
}
|
||||
|
||||
static inline bool is_mmu_index_32(int mmu_index)
|
||||
{
|
||||
assert(mmu_index < MMU_PHYS_IDX);
|
||||
return mmu_index & 1;
|
||||
}
|
||||
|
||||
static inline int cpu_mmu_index_kernel(CPUX86State *env)
|
||||
{
|
||||
return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
|
||||
((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK))
|
||||
? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
|
||||
int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 1 : 0;
|
||||
int mmu_index_base =
|
||||
!(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
|
||||
((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
|
||||
|
||||
return mmu_index_base + mmu_index_32;
|
||||
}
|
||||
|
||||
#define CC_DST (env->cc_dst)
|
||||
|
|
|
@ -134,10 +134,9 @@ static inline bool ptw_setl(const PTETranslate *in, uint32_t old, uint32_t set)
|
|||
static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
||||
TranslateResult *out, TranslateFault *err)
|
||||
{
|
||||
const int32_t a20_mask = x86_get_a20_mask(env);
|
||||
const target_ulong addr = in->addr;
|
||||
const int pg_mode = in->pg_mode;
|
||||
const bool is_user = (in->mmu_idx == MMU_USER_IDX);
|
||||
const bool is_user = is_mmu_index_user(in->mmu_idx);
|
||||
const MMUAccessType access_type = in->access_type;
|
||||
uint64_t ptep, pte, rsvd_mask;
|
||||
PTETranslate pte_trans = {
|
||||
|
@ -164,8 +163,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 5
|
||||
*/
|
||||
pte_addr = ((in->cr3 & ~0xfff) +
|
||||
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
|
||||
pte_addr = (in->cr3 & ~0xfff) + (((addr >> 48) & 0x1ff) << 3);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -189,8 +187,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 4
|
||||
*/
|
||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
||||
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
|
||||
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 39) & 0x1ff) << 3);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -210,8 +207,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 3
|
||||
*/
|
||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
||||
(((addr >> 30) & 0x1ff) << 3)) & a20_mask;
|
||||
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -238,7 +234,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 3
|
||||
*/
|
||||
pte_addr = ((in->cr3 & ~0x1f) + ((addr >> 27) & 0x18)) & a20_mask;
|
||||
pte_addr = (in->cr3 & 0xffffffe0ULL) + ((addr >> 27) & 0x18);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -260,8 +256,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 2
|
||||
*/
|
||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
||||
(((addr >> 21) & 0x1ff) << 3)) & a20_mask;
|
||||
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -287,8 +282,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 1
|
||||
*/
|
||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
||||
(((addr >> 12) & 0x1ff) << 3)) & a20_mask;
|
||||
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -306,7 +300,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 2
|
||||
*/
|
||||
pte_addr = ((in->cr3 & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
|
||||
pte_addr = (in->cr3 & 0xfffff000ULL) + ((addr >> 20) & 0xffc);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -335,7 +329,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||
/*
|
||||
* Page table level 1
|
||||
*/
|
||||
pte_addr = ((pte & ~0xfffu) + ((addr >> 10) & 0xffc)) & a20_mask;
|
||||
pte_addr = (pte & ~0xfffu) + ((addr >> 10) & 0xffc);
|
||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -363,7 +357,7 @@ do_check_protect_pse36:
|
|||
}
|
||||
|
||||
int prot = 0;
|
||||
if (in->mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
|
||||
if (!is_mmu_index_smap(in->mmu_idx) || !(ptep & PG_USER_MASK)) {
|
||||
prot |= PAGE_READ;
|
||||
if ((ptep & PG_RW_MASK) || !(is_user || (pg_mode & PG_MODE_WP))) {
|
||||
prot |= PAGE_WRITE;
|
||||
|
@ -422,10 +416,13 @@ do_check_protect_pse36:
|
|||
}
|
||||
}
|
||||
|
||||
/* align to page_size */
|
||||
paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
|
||||
| (addr & (page_size - 1));
|
||||
/* merge offset within page */
|
||||
paddr = (pte & PG_ADDRESS_MASK & ~(page_size - 1)) | (addr & (page_size - 1));
|
||||
|
||||
/*
|
||||
* Note that NPT is walked (for both paging structures and final guest
|
||||
* addresses) using the address with the A20 bit set.
|
||||
*/
|
||||
if (in->ptw_idx == MMU_NESTED_IDX) {
|
||||
CPUTLBEntryFull *full;
|
||||
int flags, nested_page_size;
|
||||
|
@ -464,7 +461,7 @@ do_check_protect_pse36:
|
|||
}
|
||||
}
|
||||
|
||||
out->paddr = paddr;
|
||||
out->paddr = paddr & x86_get_a20_mask(env);
|
||||
out->prot = prot;
|
||||
out->page_size = page_size;
|
||||
return true;
|
||||
|
@ -545,7 +542,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||
if (likely(use_stage2)) {
|
||||
in.cr3 = env->nested_cr3;
|
||||
in.pg_mode = env->nested_pg_mode;
|
||||
in.mmu_idx = MMU_USER_IDX;
|
||||
in.mmu_idx =
|
||||
env->nested_pg_mode & PG_MODE_LMA ? MMU_USER64_IDX : MMU_USER32_IDX;
|
||||
in.ptw_idx = MMU_PHYS_IDX;
|
||||
|
||||
if (!mmu_translate(env, &in, out, err)) {
|
||||
|
@ -557,6 +555,10 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||
break;
|
||||
|
||||
default:
|
||||
if (is_mmu_index_32(mmu_idx)) {
|
||||
addr = (uint32_t)addr;
|
||||
}
|
||||
|
||||
if (likely(env->cr[0] & CR0_PG_MASK)) {
|
||||
in.cr3 = env->cr[3];
|
||||
in.mmu_idx = mmu_idx;
|
||||
|
@ -580,14 +582,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Translation disabled. */
|
||||
/* No translation needed. */
|
||||
out->paddr = addr & x86_get_a20_mask(env);
|
||||
#ifdef TARGET_X86_64
|
||||
if (!(env->hflags & HF_LMA_MASK)) {
|
||||
/* Without long mode we can only address 32bits in real mode */
|
||||
out->paddr = (uint32_t)out->paddr;
|
||||
}
|
||||
#endif
|
||||
out->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
out->page_size = TARGET_PAGE_SIZE;
|
||||
return true;
|
||||
|
|
|
@ -212,6 +212,9 @@ void helper_wrmsr(CPUX86State *env)
|
|||
tlb_flush(cs);
|
||||
break;
|
||||
case MSR_VM_HSAVE_PA:
|
||||
if (val & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||
goto error;
|
||||
}
|
||||
env->vm_hsave = val;
|
||||
break;
|
||||
#ifdef TARGET_X86_64
|
||||
|
|
|
@ -164,14 +164,19 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||
uint64_t new_cr3;
|
||||
uint64_t new_cr4;
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
|
||||
|
||||
if (aflag == 2) {
|
||||
addr = env->regs[R_EAX];
|
||||
} else {
|
||||
addr = (uint32_t)env->regs[R_EAX];
|
||||
}
|
||||
|
||||
/* Exceptions are checked before the intercept. */
|
||||
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||
}
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
|
||||
|
||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
|
||||
|
||||
env->vm_vmcb = addr;
|
||||
|
@ -463,14 +468,19 @@ void helper_vmload(CPUX86State *env, int aflag)
|
|||
int mmu_idx = MMU_PHYS_IDX;
|
||||
target_ulong addr;
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
||||
|
||||
if (aflag == 2) {
|
||||
addr = env->regs[R_EAX];
|
||||
} else {
|
||||
addr = (uint32_t)env->regs[R_EAX];
|
||||
}
|
||||
|
||||
/* Exceptions are checked before the intercept. */
|
||||
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||
}
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
||||
|
||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
|
||||
mmu_idx = MMU_NESTED_IDX;
|
||||
}
|
||||
|
@ -519,14 +529,19 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
|||
int mmu_idx = MMU_PHYS_IDX;
|
||||
target_ulong addr;
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
||||
|
||||
if (aflag == 2) {
|
||||
addr = env->regs[R_EAX];
|
||||
} else {
|
||||
addr = (uint32_t)env->regs[R_EAX];
|
||||
}
|
||||
|
||||
/* Exceptions are checked before the intercept. */
|
||||
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||
}
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
||||
|
||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
|
||||
mmu_idx = MMU_NESTED_IDX;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue