diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index ed3cbc58305914561c28dad08004ccbcab8a5dca..cc5c9b0b72c384b8c3974c50c92cc77aa8f69daf 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -467,8 +467,9 @@ static int northbridge_init_f18h_m4h(const struct pci_device_id *root_ids, amd_northbridges.nb = NULL; ret: - pr_err("Hygon Fam%xh Model%xh northbridge init failed(%d)!\n", - boot_cpu_data.x86, boot_cpu_data.x86_model, err); + if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) + pr_err("Hygon Fam%xh Model%xh northbridge init failed(%d)!\n", + boot_cpu_data.x86, boot_cpu_data.x86_model, err); return err; } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 89543149d890c35d226a14b9a8c5a3d76f75bbad..319ff8781e5319f552623401b96aef1058ef04bb 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -243,6 +243,17 @@ module_param(intercept_smi, bool, 0444); bool vnmi = true; module_param(vnmi, bool, 0444); +/* + * Allow set guest PAT to WB in some non-passthrough + * application scenarios to enhance performance. + * + * Add kernel parameter set_guest_pat_wb(default 0): + * 1 - set guest PAT to WB + * 0 - keep guest PAT to the kernel default value + */ +static int set_guest_pat_wb; +module_param(set_guest_pat_wb, int, 0444); + static bool svm_gp_erratum_intercept = true; static u8 rsm_ins_bytes[] = "\x0f\xaa"; @@ -1256,6 +1267,16 @@ static inline void init_vmcb_after_set_cpuid(struct kvm_vcpu *vcpu) } } +static void svm_set_guest_pat(struct vcpu_svm *svm, u64 *g_pat) +{ + struct kvm_vcpu *vcpu = &svm->vcpu; + + if (!kvm_arch_has_assigned_device(vcpu->kvm)) + *g_pat = GUEST_PAT_WB_ATTR; + else + *g_pat = vcpu->arch.pat; +} + static void init_vmcb(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -1357,6 +1378,8 @@ static void init_vmcb(struct kvm_vcpu *vcpu) svm_clr_intercept(svm, INTERCEPT_CR3_READ); svm_clr_intercept(svm, INTERCEPT_CR3_WRITE); save->g_pat = vcpu->arch.pat; + if (set_guest_pat_wb) + svm_set_guest_pat(svm, &save->g_pat); save->cr3 = 0; } svm->current_vmcb->asid_generation = 0; @@ -3070,6 +3093,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) svm->vmcb01.ptr->save.g_pat = data; if (is_guest_mode(vcpu)) nested_vmcb02_compute_g_pat(svm); + if (npt_enabled && set_guest_pat_wb) { + svm_set_guest_pat(svm, &svm->vmcb01.ptr->save.g_pat); + vcpu->arch.pat = svm->vmcb01.ptr->save.g_pat; + } vmcb_mark_dirty(svm->vmcb, VMCB_NPT); break; case MSR_IA32_SPEC_CTRL: diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index aaf945935ff7ca9e61384c158022f80aef550473..b87a74235b43e486ca26efc3d05e798c1ca03c31 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -30,6 +30,8 @@ #define IOPM_SIZE PAGE_SIZE * 3 #define MSRPM_SIZE PAGE_SIZE * 2 +#define GUEST_PAT_WB_ATTR 0x0606060606060606 + #define MAX_DIRECT_ACCESS_MSRS 48 #define MSRPM_OFFSETS 32 extern u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly; diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index d0ab59e80fb09aa969f375371c318ddba87ca87b..5890c656590400e91c0221a987e37430b3b0c544 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1130,7 +1130,12 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr { u64 dram_base_addr, dram_limit_addr, dram_hole_base; - u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask; + u8 die_id_shift, socket_id_shift; +#ifdef CONFIG_CPU_SUP_HYGON + u16 die_id_mask, socket_id_mask; +#else + u8 die_id_mask, socket_id_mask; +#endif u8 intlv_num_dies, intlv_num_chan, intlv_num_sockets; u8 intlv_addr_sel, intlv_addr_bit; u8 num_intlv_bits, hashed_bit; @@ -1202,6 +1207,12 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr intlv_addr_bit = intlv_addr_sel + 8; + if (hygon_f18h_m4h() && boot_cpu_data.x86_model >= 0x6) { + if (df_indirect_read_instance(nid, 0, 0x60, umc, &ctx.tmp)) + goto out_err; + intlv_num_dies = ctx.tmp & 0x3; + } + /* Re-use intlv_num_chan by setting it equal to log2(#channels) */ switch (intlv_num_chan) { case 0: intlv_num_chan = 0; break; @@ -1245,7 +1256,12 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr if (num_intlv_bits > 0) { u64 temp_addr_x, temp_addr_i, temp_addr_y; - u8 die_id_bit, sock_id_bit, cs_fabric_id; + u8 die_id_bit, sock_id_bit; +#ifdef CONFIG_CPU_SUP_HYGON + u16 cs_fabric_id; +#else + u8 cs_fabric_id; +#endif /* * Read FabricBlockInstanceInformation3_CS[BlockFabricID]. @@ -1282,12 +1298,14 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr if (hygon_f18h_m4h()) { die_id_shift = (ctx.tmp >> 12) & 0xF; die_id_mask = ctx.tmp & 0x7FF; + cs_id |= (((cs_fabric_id & die_id_mask) >> die_id_shift) - 4) << + die_id_bit; } else { die_id_shift = (ctx.tmp >> 24) & 0xF; die_id_mask = (ctx.tmp >> 8) & 0xFF; + cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << + die_id_bit; } - - cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit; } /* If interleaved over more than 1 socket. */ @@ -3148,8 +3166,8 @@ static void decode_umc_error(int node_id, struct mce *m) pvt->ops->get_err_info(m, &err); - if (hygon_f18h_m4h() && boot_cpu_data.x86_model == 0x6) - umc = err.channel << 1; + if (hygon_f18h_m4h() && boot_cpu_data.x86_model >= 0x6) + umc = (err.channel << 1) + ((m->ipid & BIT(13)) >> 13); else umc = err.channel; diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 75bff325a42519115b532e53231ed9c932c2b537..6833934a3b05346cb796cdc4fa31d663db60429a 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -1207,6 +1207,7 @@ static const struct acpi_device_id amd_gpio_acpi_match[] = { { "AMD0030", 0 }, { "AMDI0030", 0}, { "AMDI0031", 0}, + { "HYGO0030", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match);