Skip to content

Commit 0f53a02

Browse files
committed
KVM: selftests: Init x86's segments during VM creation
Initialize x86's various segments in the GDT during creation of relevant VMs instead of waiting until vCPUs come along. Re-installing the segments for every vCPU is both wasteful and confusing, as is installing KERNEL_DS multiple times; NOT installing KERNEL_DS for GS is icing on the cake. Reviewed-by: Ackerley Tng <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent f18ef97 commit 0f53a02

File tree

1 file changed

+20
-48
lines changed

1 file changed

+20
-48
lines changed

tools/testing/selftests/kvm/lib/x86_64/processor.c

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -439,24 +439,7 @@ static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
439439
desc->base3 = segp->base >> 32;
440440
}
441441

442-
443-
/*
444-
* Set Long Mode Flat Kernel Code Segment
445-
*
446-
* Input Args:
447-
* vm - VM whose GDT is being filled, or NULL to only write segp
448-
* selector - selector value
449-
*
450-
* Output Args:
451-
* segp - Pointer to KVM segment
452-
*
453-
* Return: None
454-
*
455-
* Sets up the KVM segment pointed to by @segp, to be a code segment
456-
* with the selector value given by @selector.
457-
*/
458-
static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
459-
struct kvm_segment *segp)
442+
static void kvm_seg_set_kernel_code_64bit(uint16_t selector, struct kvm_segment *segp)
460443
{
461444
memset(segp, 0, sizeof(*segp));
462445
segp->selector = selector;
@@ -468,27 +451,9 @@ static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
468451
segp->g = true;
469452
segp->l = true;
470453
segp->present = 1;
471-
if (vm)
472-
kvm_seg_fill_gdt_64bit(vm, segp);
473454
}
474455

475-
/*
476-
* Set Long Mode Flat Kernel Data Segment
477-
*
478-
* Input Args:
479-
* vm - VM whose GDT is being filled, or NULL to only write segp
480-
* selector - selector value
481-
*
482-
* Output Args:
483-
* segp - Pointer to KVM segment
484-
*
485-
* Return: None
486-
*
487-
* Sets up the KVM segment pointed to by @segp, to be a data segment
488-
* with the selector value given by @selector.
489-
*/
490-
static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
491-
struct kvm_segment *segp)
456+
static void kvm_seg_set_kernel_data_64bit(uint16_t selector, struct kvm_segment *segp)
492457
{
493458
memset(segp, 0, sizeof(*segp));
494459
segp->selector = selector;
@@ -499,8 +464,6 @@ static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
499464
*/
500465
segp->g = true;
501466
segp->present = true;
502-
if (vm)
503-
kvm_seg_fill_gdt_64bit(vm, segp);
504467
}
505468

506469
vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
@@ -518,16 +481,15 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
518481
return vm_untag_gpa(vm, PTE_GET_PA(*pte)) | (gva & ~HUGEPAGE_MASK(level));
519482
}
520483

521-
static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
522-
int selector)
484+
static void kvm_seg_set_tss_64bit(vm_vaddr_t base, struct kvm_segment *segp,
485+
int selector)
523486
{
524487
memset(segp, 0, sizeof(*segp));
525-
segp->base = vm->arch.tss;
488+
segp->base = base;
526489
segp->limit = 0x67;
527490
segp->selector = selector;
528491
segp->type = 0xb;
529492
segp->present = 1;
530-
kvm_seg_fill_gdt_64bit(vm, segp);
531493
}
532494

533495
static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
@@ -549,11 +511,11 @@ static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
549511
sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
550512

551513
kvm_seg_set_unusable(&sregs.ldt);
552-
kvm_seg_set_kernel_code_64bit(vm, KERNEL_CS, &sregs.cs);
553-
kvm_seg_set_kernel_data_64bit(vm, KERNEL_DS, &sregs.ds);
554-
kvm_seg_set_kernel_data_64bit(vm, KERNEL_DS, &sregs.es);
555-
kvm_seg_set_kernel_data_64bit(NULL, KERNEL_DS, &sregs.gs);
556-
kvm_setup_tss_64bit(vm, &sregs.tr, KERNEL_TSS);
514+
kvm_seg_set_kernel_code_64bit(KERNEL_CS, &sregs.cs);
515+
kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.ds);
516+
kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.es);
517+
kvm_seg_set_kernel_data_64bit(KERNEL_DS, &sregs.gs);
518+
kvm_seg_set_tss_64bit(vm->arch.tss, &sregs.tr, KERNEL_TSS);
557519

558520
sregs.cr3 = vm->pgd;
559521
vcpu_sregs_set(vcpu, &sregs);
@@ -613,6 +575,7 @@ void route_exception(struct ex_regs *regs)
613575
static void vm_init_descriptor_tables(struct kvm_vm *vm)
614576
{
615577
extern void *idt_handlers;
578+
struct kvm_segment seg;
616579
int i;
617580

618581
vm->arch.gdt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
@@ -625,6 +588,15 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm)
625588
set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0, KERNEL_CS);
626589

627590
*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
591+
592+
kvm_seg_set_kernel_code_64bit(KERNEL_CS, &seg);
593+
kvm_seg_fill_gdt_64bit(vm, &seg);
594+
595+
kvm_seg_set_kernel_data_64bit(KERNEL_DS, &seg);
596+
kvm_seg_fill_gdt_64bit(vm, &seg);
597+
598+
kvm_seg_set_tss_64bit(vm->arch.tss, &seg, KERNEL_TSS);
599+
kvm_seg_fill_gdt_64bit(vm, &seg);
628600
}
629601

630602
void vm_install_exception_handler(struct kvm_vm *vm, int vector,

0 commit comments

Comments
 (0)