31
31
#include <asm/iommu.h>
32
32
33
33
/*
34
- * The RMP entry format is not architectural. The format is defined in PPR
35
- * Family 19h Model 01h, Rev B1 processor.
34
+ * The RMP entry information as returned by the RMPREAD instruction.
36
35
*/
37
36
struct rmpentry {
37
+ u64 gpa ;
38
+ u8 assigned :1 ,
39
+ rsvd1 :7 ;
40
+ u8 pagesize :1 ,
41
+ hpage_region_status :1 ,
42
+ rsvd2 :6 ;
43
+ u8 immutable :1 ,
44
+ rsvd3 :7 ;
45
+ u8 rsvd4 ;
46
+ u32 asid ;
47
+ } __packed ;
48
+
49
+ /*
50
+ * The raw RMP entry format is not architectural. The format is defined in PPR
51
+ * Family 19h Model 01h, Rev B1 processor. This format represents the actual
52
+ * entry in the RMP table memory. The bitfield definitions are used for machines
53
+ * without the RMPREAD instruction (Zen3 and Zen4), otherwise the "hi" and "lo"
54
+ * fields are only used for dumping the raw data.
55
+ */
56
+ struct rmpentry_raw {
38
57
union {
39
58
struct {
40
59
u64 assigned : 1 ,
@@ -62,7 +81,7 @@ struct rmpentry {
62
81
#define PFN_PMD_MASK GENMASK_ULL(63, PMD_SHIFT - PAGE_SHIFT)
63
82
64
83
static u64 probed_rmp_base , probed_rmp_size ;
65
- static struct rmpentry * rmptable __ro_after_init ;
84
+ static struct rmpentry_raw * rmptable __ro_after_init ;
66
85
static u64 rmptable_max_pfn __ro_after_init ;
67
86
68
87
static LIST_HEAD (snp_leaked_pages_list );
@@ -249,8 +268,8 @@ static int __init snp_rmptable_init(void)
249
268
rmptable_start += RMPTABLE_CPU_BOOKKEEPING_SZ ;
250
269
rmptable_size = probed_rmp_size - RMPTABLE_CPU_BOOKKEEPING_SZ ;
251
270
252
- rmptable = (struct rmpentry * )rmptable_start ;
253
- rmptable_max_pfn = rmptable_size / sizeof (struct rmpentry ) - 1 ;
271
+ rmptable = (struct rmpentry_raw * )rmptable_start ;
272
+ rmptable_max_pfn = rmptable_size / sizeof (struct rmpentry_raw ) - 1 ;
254
273
255
274
cpuhp_setup_state (CPUHP_AP_ONLINE_DYN , "x86/rmptable_init:online" , __snp_enable , NULL );
256
275
@@ -272,48 +291,77 @@ static int __init snp_rmptable_init(void)
272
291
*/
273
292
device_initcall (snp_rmptable_init );
274
293
275
- static struct rmpentry * get_rmpentry (u64 pfn )
294
+ static struct rmpentry_raw * get_raw_rmpentry (u64 pfn )
276
295
{
277
- if (WARN_ON_ONCE (pfn > rmptable_max_pfn ))
296
+ if (!rmptable )
297
+ return ERR_PTR (- ENODEV );
298
+
299
+ if (unlikely (pfn > rmptable_max_pfn ))
278
300
return ERR_PTR (- EFAULT );
279
301
280
- return & rmptable [pfn ];
302
+ return rmptable + pfn ;
303
+ }
304
+
305
+ static int get_rmpentry (u64 pfn , struct rmpentry * e )
306
+ {
307
+ struct rmpentry_raw * e_raw ;
308
+
309
+ e_raw = get_raw_rmpentry (pfn );
310
+ if (IS_ERR (e_raw ))
311
+ return PTR_ERR (e_raw );
312
+
313
+ /*
314
+ * Map the raw RMP table entry onto the RMPREAD output format.
315
+ * The 2MB region status indicator (hpage_region_status field) is not
316
+ * calculated, since the overhead could be significant and the field
317
+ * is not used.
318
+ */
319
+ memset (e , 0 , sizeof (* e ));
320
+ e -> gpa = e_raw -> gpa << PAGE_SHIFT ;
321
+ e -> asid = e_raw -> asid ;
322
+ e -> assigned = e_raw -> assigned ;
323
+ e -> pagesize = e_raw -> pagesize ;
324
+ e -> immutable = e_raw -> immutable ;
325
+
326
+ return 0 ;
281
327
}
282
328
283
- static struct rmpentry * __snp_lookup_rmpentry (u64 pfn , int * level )
329
+ static int __snp_lookup_rmpentry (u64 pfn , struct rmpentry * e , int * level )
284
330
{
285
- struct rmpentry * large_entry , * entry ;
331
+ struct rmpentry e_large ;
332
+ int ret ;
286
333
287
334
if (!cc_platform_has (CC_ATTR_HOST_SEV_SNP ))
288
- return ERR_PTR ( - ENODEV ) ;
335
+ return - ENODEV ;
289
336
290
- entry = get_rmpentry (pfn );
291
- if (IS_ERR ( entry ) )
292
- return entry ;
337
+ ret = get_rmpentry (pfn , e );
338
+ if (ret )
339
+ return ret ;
293
340
294
341
/*
295
342
* Find the authoritative RMP entry for a PFN. This can be either a 4K
296
343
* RMP entry or a special large RMP entry that is authoritative for a
297
344
* whole 2M area.
298
345
*/
299
- large_entry = get_rmpentry (pfn & PFN_PMD_MASK );
300
- if (IS_ERR ( large_entry ) )
301
- return large_entry ;
346
+ ret = get_rmpentry (pfn & PFN_PMD_MASK , & e_large );
347
+ if (ret )
348
+ return ret ;
302
349
303
- * level = RMP_TO_PG_LEVEL (large_entry -> pagesize );
350
+ * level = RMP_TO_PG_LEVEL (e_large . pagesize );
304
351
305
- return entry ;
352
+ return 0 ;
306
353
}
307
354
308
355
int snp_lookup_rmpentry (u64 pfn , bool * assigned , int * level )
309
356
{
310
- struct rmpentry * e ;
357
+ struct rmpentry e ;
358
+ int ret ;
311
359
312
- e = __snp_lookup_rmpentry (pfn , level );
313
- if (IS_ERR ( e ) )
314
- return PTR_ERR ( e ) ;
360
+ ret = __snp_lookup_rmpentry (pfn , & e , level );
361
+ if (ret )
362
+ return ret ;
315
363
316
- * assigned = !!e -> assigned ;
364
+ * assigned = !!e . assigned ;
317
365
return 0 ;
318
366
}
319
367
EXPORT_SYMBOL_GPL (snp_lookup_rmpentry );
@@ -326,20 +374,28 @@ EXPORT_SYMBOL_GPL(snp_lookup_rmpentry);
326
374
*/
327
375
static void dump_rmpentry (u64 pfn )
328
376
{
377
+ struct rmpentry_raw * e_raw ;
329
378
u64 pfn_i , pfn_end ;
330
- struct rmpentry * e ;
331
- int level ;
379
+ struct rmpentry e ;
380
+ int level , ret ;
332
381
333
- e = __snp_lookup_rmpentry (pfn , & level );
334
- if (IS_ERR ( e ) ) {
335
- pr_err ("Failed to read RMP entry for PFN 0x%llx, error %ld \n" ,
336
- pfn , PTR_ERR ( e ) );
382
+ ret = __snp_lookup_rmpentry (pfn , & e , & level );
383
+ if (ret ) {
384
+ pr_err ("Failed to read RMP entry for PFN 0x%llx, error %d \n" ,
385
+ pfn , ret );
337
386
return ;
338
387
}
339
388
340
- if (e -> assigned ) {
389
+ if (e .assigned ) {
390
+ e_raw = get_raw_rmpentry (pfn );
391
+ if (IS_ERR (e_raw )) {
392
+ pr_err ("Failed to read RMP contents for PFN 0x%llx, error %ld\n" ,
393
+ pfn , PTR_ERR (e_raw ));
394
+ return ;
395
+ }
396
+
341
397
pr_info ("PFN 0x%llx, RMP entry: [0x%016llx - 0x%016llx]\n" ,
342
- pfn , e -> lo , e -> hi );
398
+ pfn , e_raw -> lo , e_raw -> hi );
343
399
return ;
344
400
}
345
401
@@ -358,16 +414,16 @@ static void dump_rmpentry(u64 pfn)
358
414
pfn , pfn_i , pfn_end );
359
415
360
416
while (pfn_i < pfn_end ) {
361
- e = __snp_lookup_rmpentry (pfn_i , & level );
362
- if (IS_ERR (e )) {
363
- pr_err ("Error %ld reading RMP entry for PFN 0x%llx\n" ,
364
- PTR_ERR (e ), pfn_i );
417
+ e_raw = get_raw_rmpentry (pfn_i );
418
+ if (IS_ERR (e_raw )) {
419
+ pr_err ("Error %ld reading RMP contents for PFN 0x%llx\n" ,
420
+ PTR_ERR (e_raw ), pfn_i );
365
421
pfn_i ++ ;
366
422
continue ;
367
423
}
368
424
369
- if (e -> lo || e -> hi )
370
- pr_info ("PFN: 0x%llx, [0x%016llx - 0x%016llx]\n" , pfn_i , e -> lo , e -> hi );
425
+ if (e_raw -> lo || e_raw -> hi )
426
+ pr_info ("PFN: 0x%llx, [0x%016llx - 0x%016llx]\n" , pfn_i , e_raw -> lo , e_raw -> hi );
371
427
pfn_i ++ ;
372
428
}
373
429
}
0 commit comments