@@ -78,6 +78,7 @@ static const char * const sev_status_feat_names[] = {
7878 [MSR_AMD64_SNP_IBS_VIRT_BIT ] = "IBSVirt" ,
7979 [MSR_AMD64_SNP_VMSA_REG_PROT_BIT ] = "VMSARegProt" ,
8080 [MSR_AMD64_SNP_SMT_PROT_BIT ] = "SMTProt" ,
81+ [MSR_AMD64_SNP_SECURE_AVIC_BIT ] = "SecureAVIC" ,
8182};
8283
8384/* For early boot hypervisor communication in SEV-ES enabled guests */
@@ -1181,6 +1182,9 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip, unsigned
11811182 vmsa -> x87_ftw = AP_INIT_X87_FTW_DEFAULT ;
11821183 vmsa -> x87_fcw = AP_INIT_X87_FCW_DEFAULT ;
11831184
1185+ if (cc_platform_has (CC_ATTR_SNP_SECURE_AVIC ))
1186+ vmsa -> vintr_ctrl |= (V_GIF_MASK | V_NMI_ENABLE_MASK );
1187+
11841188 /* SVME must be set. */
11851189 vmsa -> efer = EFER_SVME ;
11861190
@@ -1322,18 +1326,14 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
13221326 return 0 ;
13231327}
13241328
1325- static enum es_result vc_handle_msr (struct ghcb * ghcb , struct es_em_ctxt * ctxt )
1329+ static enum es_result sev_es_ghcb_handle_msr (struct ghcb * ghcb , struct es_em_ctxt * ctxt , bool write )
13261330{
13271331 struct pt_regs * regs = ctxt -> regs ;
13281332 enum es_result ret ;
1329- u64 exit_info_1 ;
1330-
1331- /* Is it a WRMSR? */
1332- exit_info_1 = (ctxt -> insn .opcode .bytes [1 ] == 0x30 ) ? 1 : 0 ;
13331333
13341334 if (regs -> cx == MSR_SVSM_CAA ) {
13351335 /* Writes to the SVSM CAA msr are ignored */
1336- if (exit_info_1 )
1336+ if (write )
13371337 return ES_OK ;
13381338
13391339 regs -> ax = lower_32_bits (this_cpu_read (svsm_caa_pa ));
@@ -1343,21 +1343,26 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
13431343 }
13441344
13451345 ghcb_set_rcx (ghcb , regs -> cx );
1346- if (exit_info_1 ) {
1346+ if (write ) {
13471347 ghcb_set_rax (ghcb , regs -> ax );
13481348 ghcb_set_rdx (ghcb , regs -> dx );
13491349 }
13501350
1351- ret = sev_es_ghcb_hv_call (ghcb , ctxt , SVM_EXIT_MSR , exit_info_1 , 0 );
1351+ ret = sev_es_ghcb_hv_call (ghcb , ctxt , SVM_EXIT_MSR , write , 0 );
13521352
1353- if ((ret == ES_OK ) && (!exit_info_1 )) {
1353+ if ((ret == ES_OK ) && (!write )) {
13541354 regs -> ax = ghcb -> save .rax ;
13551355 regs -> dx = ghcb -> save .rdx ;
13561356 }
13571357
13581358 return ret ;
13591359}
13601360
1361+ static enum es_result vc_handle_msr (struct ghcb * ghcb , struct es_em_ctxt * ctxt )
1362+ {
1363+ return sev_es_ghcb_handle_msr (ghcb , ctxt , ctxt -> insn .opcode .bytes [1 ] == 0x30 );
1364+ }
1365+
13611366static void snp_register_per_cpu_ghcb (void )
13621367{
13631368 struct sev_es_runtime_data * data ;
@@ -2066,6 +2071,105 @@ static bool vc_raw_handle_exception(struct pt_regs *regs, unsigned long error_co
20662071 return ret ;
20672072}
20682073
2074+ u64 savic_ghcb_msr_read (u32 reg )
2075+ {
2076+ u64 msr = APIC_BASE_MSR + (reg >> 4 );
2077+ struct pt_regs regs = { .cx = msr };
2078+ struct es_em_ctxt ctxt = { .regs = & regs };
2079+ struct ghcb_state state ;
2080+ enum es_result res ;
2081+ struct ghcb * ghcb ;
2082+
2083+ guard (irqsave )();
2084+
2085+ ghcb = __sev_get_ghcb (& state );
2086+ vc_ghcb_invalidate (ghcb );
2087+
2088+ res = sev_es_ghcb_handle_msr (ghcb , & ctxt , false);
2089+ if (res != ES_OK ) {
2090+ pr_err ("Secure AVIC msr (0x%llx) read returned error (%d)\n" , msr , res );
2091+ /* MSR read failures are treated as fatal errors */
2092+ snp_abort ();
2093+ }
2094+
2095+ __sev_put_ghcb (& state );
2096+
2097+ return regs .ax | regs .dx << 32 ;
2098+ }
2099+
2100+ void savic_ghcb_msr_write (u32 reg , u64 value )
2101+ {
2102+ u64 msr = APIC_BASE_MSR + (reg >> 4 );
2103+ struct pt_regs regs = {
2104+ .cx = msr ,
2105+ .ax = lower_32_bits (value ),
2106+ .dx = upper_32_bits (value )
2107+ };
2108+ struct es_em_ctxt ctxt = { .regs = & regs };
2109+ struct ghcb_state state ;
2110+ enum es_result res ;
2111+ struct ghcb * ghcb ;
2112+
2113+ guard (irqsave )();
2114+
2115+ ghcb = __sev_get_ghcb (& state );
2116+ vc_ghcb_invalidate (ghcb );
2117+
2118+ res = sev_es_ghcb_handle_msr (ghcb , & ctxt , true);
2119+ if (res != ES_OK ) {
2120+ pr_err ("Secure AVIC msr (0x%llx) write returned error (%d)\n" , msr , res );
2121+ /* MSR writes should never fail. Any failure is fatal error for SNP guest */
2122+ snp_abort ();
2123+ }
2124+
2125+ __sev_put_ghcb (& state );
2126+ }
2127+
2128+ enum es_result savic_register_gpa (u64 gpa )
2129+ {
2130+ struct ghcb_state state ;
2131+ struct es_em_ctxt ctxt ;
2132+ enum es_result res ;
2133+ struct ghcb * ghcb ;
2134+
2135+ guard (irqsave )();
2136+
2137+ ghcb = __sev_get_ghcb (& state );
2138+ vc_ghcb_invalidate (ghcb );
2139+
2140+ ghcb_set_rax (ghcb , SVM_VMGEXIT_SAVIC_SELF_GPA );
2141+ ghcb_set_rbx (ghcb , gpa );
2142+ res = sev_es_ghcb_hv_call (ghcb , & ctxt , SVM_VMGEXIT_SAVIC ,
2143+ SVM_VMGEXIT_SAVIC_REGISTER_GPA , 0 );
2144+
2145+ __sev_put_ghcb (& state );
2146+
2147+ return res ;
2148+ }
2149+
2150+ enum es_result savic_unregister_gpa (u64 * gpa )
2151+ {
2152+ struct ghcb_state state ;
2153+ struct es_em_ctxt ctxt ;
2154+ enum es_result res ;
2155+ struct ghcb * ghcb ;
2156+
2157+ guard (irqsave )();
2158+
2159+ ghcb = __sev_get_ghcb (& state );
2160+ vc_ghcb_invalidate (ghcb );
2161+
2162+ ghcb_set_rax (ghcb , SVM_VMGEXIT_SAVIC_SELF_GPA );
2163+ res = sev_es_ghcb_hv_call (ghcb , & ctxt , SVM_VMGEXIT_SAVIC ,
2164+ SVM_VMGEXIT_SAVIC_UNREGISTER_GPA , 0 );
2165+ if (gpa && res == ES_OK )
2166+ * gpa = ghcb -> save .rbx ;
2167+
2168+ __sev_put_ghcb (& state );
2169+
2170+ return res ;
2171+ }
2172+
20692173static __always_inline bool vc_is_db (unsigned long error_code )
20702174{
20712175 return error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB ;
0 commit comments