Skip to content

Commit b62c32c

Browse files
committed
KVM: selftests: Move x86's descriptor table helpers "up" in processor.c
Move x86's various descriptor table helpers in processor.c up above kvm_arch_vm_post_create() and vcpu_setup() so that the helpers can be made static and invoked from the aforementioned functions. No functional change intended. Reviewed-by: Ackerley Tng <ackerleytng@google.com> Link: https://lore.kernel.org/r/20240314232637.2538648-9-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 61c3cff commit b62c32c

File tree

1 file changed

+95
-96
lines changed

1 file changed

+95
-96
lines changed

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

Lines changed: 95 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,21 @@ static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
541541
kvm_seg_fill_gdt_64bit(vm, segp);
542542
}
543543

544+
void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
545+
{
546+
struct kvm_vm *vm = vcpu->vm;
547+
struct kvm_sregs sregs;
548+
549+
vcpu_sregs_get(vcpu, &sregs);
550+
sregs.idt.base = vm->arch.idt;
551+
sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
552+
sregs.gdt.base = vm->arch.gdt;
553+
sregs.gdt.limit = getpagesize() - 1;
554+
kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
555+
vcpu_sregs_set(vcpu, &sregs);
556+
*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
557+
}
558+
544559
static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
545560
{
546561
struct kvm_sregs sregs;
@@ -573,6 +588,86 @@ static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
573588
vcpu_sregs_set(vcpu, &sregs);
574589
}
575590

591+
static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
592+
int dpl, unsigned short selector)
593+
{
594+
struct idt_entry *base =
595+
(struct idt_entry *)addr_gva2hva(vm, vm->arch.idt);
596+
struct idt_entry *e = &base[vector];
597+
598+
memset(e, 0, sizeof(*e));
599+
e->offset0 = addr;
600+
e->selector = selector;
601+
e->ist = 0;
602+
e->type = 14;
603+
e->dpl = dpl;
604+
e->p = 1;
605+
e->offset1 = addr >> 16;
606+
e->offset2 = addr >> 32;
607+
}
608+
609+
static bool kvm_fixup_exception(struct ex_regs *regs)
610+
{
611+
if (regs->r9 != KVM_EXCEPTION_MAGIC || regs->rip != regs->r10)
612+
return false;
613+
614+
if (regs->vector == DE_VECTOR)
615+
return false;
616+
617+
regs->rip = regs->r11;
618+
regs->r9 = regs->vector;
619+
regs->r10 = regs->error_code;
620+
return true;
621+
}
622+
623+
void route_exception(struct ex_regs *regs)
624+
{
625+
typedef void(*handler)(struct ex_regs *);
626+
handler *handlers = (handler *)exception_handlers;
627+
628+
if (handlers && handlers[regs->vector]) {
629+
handlers[regs->vector](regs);
630+
return;
631+
}
632+
633+
if (kvm_fixup_exception(regs))
634+
return;
635+
636+
ucall_assert(UCALL_UNHANDLED,
637+
"Unhandled exception in guest", __FILE__, __LINE__,
638+
"Unhandled exception '0x%lx' at guest RIP '0x%lx'",
639+
regs->vector, regs->rip);
640+
}
641+
642+
void vm_init_descriptor_tables(struct kvm_vm *vm)
643+
{
644+
extern void *idt_handlers;
645+
int i;
646+
647+
vm->arch.idt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
648+
vm->handlers = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
649+
/* Handlers have the same address in both address spaces.*/
650+
for (i = 0; i < NUM_INTERRUPTS; i++)
651+
set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
652+
DEFAULT_CODE_SELECTOR);
653+
}
654+
655+
void vm_install_exception_handler(struct kvm_vm *vm, int vector,
656+
void (*handler)(struct ex_regs *))
657+
{
658+
vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
659+
660+
handlers[vector] = (vm_vaddr_t)handler;
661+
}
662+
663+
void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
664+
{
665+
struct ucall uc;
666+
667+
if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED)
668+
REPORT_GUEST_ASSERT(uc);
669+
}
670+
576671
void kvm_arch_vm_post_create(struct kvm_vm *vm)
577672
{
578673
vm_create_irqchip(vm);
@@ -1093,102 +1188,6 @@ void kvm_init_vm_address_properties(struct kvm_vm *vm)
10931188
}
10941189
}
10951190

1096-
static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
1097-
int dpl, unsigned short selector)
1098-
{
1099-
struct idt_entry *base =
1100-
(struct idt_entry *)addr_gva2hva(vm, vm->arch.idt);
1101-
struct idt_entry *e = &base[vector];
1102-
1103-
memset(e, 0, sizeof(*e));
1104-
e->offset0 = addr;
1105-
e->selector = selector;
1106-
e->ist = 0;
1107-
e->type = 14;
1108-
e->dpl = dpl;
1109-
e->p = 1;
1110-
e->offset1 = addr >> 16;
1111-
e->offset2 = addr >> 32;
1112-
}
1113-
1114-
1115-
static bool kvm_fixup_exception(struct ex_regs *regs)
1116-
{
1117-
if (regs->r9 != KVM_EXCEPTION_MAGIC || regs->rip != regs->r10)
1118-
return false;
1119-
1120-
if (regs->vector == DE_VECTOR)
1121-
return false;
1122-
1123-
regs->rip = regs->r11;
1124-
regs->r9 = regs->vector;
1125-
regs->r10 = regs->error_code;
1126-
return true;
1127-
}
1128-
1129-
void route_exception(struct ex_regs *regs)
1130-
{
1131-
typedef void(*handler)(struct ex_regs *);
1132-
handler *handlers = (handler *)exception_handlers;
1133-
1134-
if (handlers && handlers[regs->vector]) {
1135-
handlers[regs->vector](regs);
1136-
return;
1137-
}
1138-
1139-
if (kvm_fixup_exception(regs))
1140-
return;
1141-
1142-
ucall_assert(UCALL_UNHANDLED,
1143-
"Unhandled exception in guest", __FILE__, __LINE__,
1144-
"Unhandled exception '0x%lx' at guest RIP '0x%lx'",
1145-
regs->vector, regs->rip);
1146-
}
1147-
1148-
void vm_init_descriptor_tables(struct kvm_vm *vm)
1149-
{
1150-
extern void *idt_handlers;
1151-
int i;
1152-
1153-
vm->arch.idt = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
1154-
vm->handlers = __vm_vaddr_alloc_page(vm, MEM_REGION_DATA);
1155-
/* Handlers have the same address in both address spaces.*/
1156-
for (i = 0; i < NUM_INTERRUPTS; i++)
1157-
set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0,
1158-
DEFAULT_CODE_SELECTOR);
1159-
}
1160-
1161-
void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
1162-
{
1163-
struct kvm_vm *vm = vcpu->vm;
1164-
struct kvm_sregs sregs;
1165-
1166-
vcpu_sregs_get(vcpu, &sregs);
1167-
sregs.idt.base = vm->arch.idt;
1168-
sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1;
1169-
sregs.gdt.base = vm->arch.gdt;
1170-
sregs.gdt.limit = getpagesize() - 1;
1171-
kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs);
1172-
vcpu_sregs_set(vcpu, &sregs);
1173-
*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
1174-
}
1175-
1176-
void vm_install_exception_handler(struct kvm_vm *vm, int vector,
1177-
void (*handler)(struct ex_regs *))
1178-
{
1179-
vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
1180-
1181-
handlers[vector] = (vm_vaddr_t)handler;
1182-
}
1183-
1184-
void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
1185-
{
1186-
struct ucall uc;
1187-
1188-
if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED)
1189-
REPORT_GUEST_ASSERT(uc);
1190-
}
1191-
11921191
const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
11931192
uint32_t function, uint32_t index)
11941193
{

0 commit comments

Comments
 (0)