@@ -405,6 +405,40 @@ static int vie_canonical_check(enum vm_cpu_mode cpu_mode, uint64_t gla)
405
405
}
406
406
}
407
407
408
+ static bool is_desc_valid (struct seg_desc * desc , uint32_t prot )
409
+ {
410
+ uint32_t type ;
411
+
412
+ /* The descriptor type must indicate a code/data segment. */
413
+ type = SEG_DESC_TYPE (desc -> access );
414
+ if (type < 16U || type > 31U ) {
415
+ return false;
416
+ }
417
+
418
+ if ((prot & PROT_READ ) != 0U ) {
419
+ /* #GP on a read access to a exec-only code segment */
420
+ if ((type & 0xAU ) == 0x8U ) {
421
+ return false;
422
+ }
423
+ }
424
+
425
+ if ((prot & PROT_WRITE ) != 0U ) {
426
+ /*
427
+ * #GP on a write access to a code segment or a
428
+ * read-only data segment.
429
+ */
430
+ if ((type & 0x8U ) != 0U ) { /* code segment */
431
+ return false;
432
+ }
433
+
434
+ if ((type & 0xAU ) == 0U ) { /* read-only data seg */
435
+ return false;
436
+ }
437
+ }
438
+
439
+ return true;
440
+ }
441
+
408
442
/*
409
443
*@pre seg must be segment register index
410
444
*@pre length_arg must be 1, 2, 4 or 8
@@ -415,57 +449,15 @@ static int vie_canonical_check(enum vm_cpu_mode cpu_mode, uint64_t gla)
415
449
*/
416
450
static int vie_calculate_gla (enum vm_cpu_mode cpu_mode , enum cpu_reg_name seg ,
417
451
struct seg_desc * desc , uint64_t offset_arg , uint8_t addrsize ,
418
- uint32_t prot , uint64_t * gla )
452
+ uint64_t * gla )
419
453
{
420
454
uint64_t firstoff , segbase ;
421
455
uint64_t offset = offset_arg ;
422
456
uint8_t glasize ;
423
457
uint32_t type ;
424
458
425
459
firstoff = offset ;
426
- if (cpu_mode == CPU_MODE_64BIT ) {
427
- if (addrsize != 4U && addrsize != 8U ) {
428
- pr_dbg ("%s: invalid addr size %d for cpu mode %d" ,
429
- __func__ , addrsize , cpu_mode );
430
- return -1 ;
431
- }
432
- glasize = 8U ;
433
- } else {
434
- if (addrsize != 2U && addrsize != 4U ) {
435
- pr_dbg ("%s: invalid addr size %d for cpu mode %d" ,
436
- __func__ , addrsize , cpu_mode );
437
- return -1 ;
438
- }
439
- glasize = 4U ;
440
-
441
- /* The descriptor type must indicate a code/data segment. */
442
- type = SEG_DESC_TYPE (desc -> access );
443
- if (type < 16 || type > 31 ) {
444
- /*TODO: Inject #GP */
445
- return -1 ;
446
- }
447
-
448
- if ((prot & PROT_READ ) != 0U ) {
449
- /* #GP on a read access to a exec-only code segment */
450
- if ((type & 0xAU ) == 0x8U ) {
451
- return -1 ;
452
- }
453
- }
454
-
455
- if ((prot & PROT_WRITE ) != 0U ) {
456
- /*
457
- * #GP on a write access to a code segment or a
458
- * read-only data segment.
459
- */
460
- if ((type & 0x8U ) != 0U ) { /* code segment */
461
- return -1 ;
462
- }
463
-
464
- if ((type & 0xAU ) == 0U ) { /* read-only data seg */
465
- return -1 ;
466
- }
467
- }
468
- }
460
+ glasize = (cpu_mode == CPU_MODE_64BIT ) ? 8U : 4U ;
469
461
470
462
/*
471
463
* In 64-bit mode all segments except %fs and %gs have a segment
@@ -886,7 +878,7 @@ static int get_gla(struct vcpu *vcpu, __unused struct instr_emul_vie *vie,
886
878
vm_get_seg_desc (seg , & desc );
887
879
888
880
if (vie_calculate_gla (paging -> cpu_mode , seg , & desc , val ,
889
- addrsize , prot , gla ) != 0 ) {
881
+ addrsize , gla ) != 0 ) {
890
882
if (seg == CPU_REG_SS ) {
891
883
pr_err ("TODO: inject ss exception" );
892
884
} else {
0 commit comments