diff options
Diffstat (limited to 'tools/testing/selftests/kvm/lib/kvm_util.c')
| -rw-r--r-- | tools/testing/selftests/kvm/lib/kvm_util.c | 133 | 
1 files changed, 132 insertions, 1 deletions
| diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 8f2e0bb1ef96..4a645dc77f34 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -85,6 +85,33 @@ int kvm_check_cap(long cap)  	return ret;  } +/* VM Check Capability + * + * Input Args: + *   vm - Virtual Machine + *   cap - Capability + * + * Output Args: None + * + * Return: + *   On success, the Value corresponding to the capability (KVM_CAP_*) + *   specified by the value of cap.  On failure a TEST_ASSERT failure + *   is produced. + * + * Looks up and returns the value corresponding to the capability + * (KVM_CAP_*) given by cap. + */ +int vm_check_cap(struct kvm_vm *vm, long cap) +{ +	int ret; + +	ret = ioctl(vm->fd, KVM_CHECK_EXTENSION, cap); +	TEST_ASSERT(ret >= 0, "KVM_CHECK_EXTENSION VM IOCTL failed,\n" +		"  rc: %i errno: %i", ret, errno); + +	return ret; +} +  /* VM Enable Capability   *   * Input Args: @@ -166,12 +193,18 @@ const char *vm_guest_mode_string(uint32_t i)  		[VM_MODE_P52V48_4K]	= "PA-bits:52,  VA-bits:48,  4K pages",  		[VM_MODE_P52V48_64K]	= "PA-bits:52,  VA-bits:48, 64K pages",  		[VM_MODE_P48V48_4K]	= "PA-bits:48,  VA-bits:48,  4K pages", +		[VM_MODE_P48V48_16K]	= "PA-bits:48,  VA-bits:48, 16K pages",  		[VM_MODE_P48V48_64K]	= "PA-bits:48,  VA-bits:48, 64K pages",  		[VM_MODE_P40V48_4K]	= "PA-bits:40,  VA-bits:48,  4K pages", +		[VM_MODE_P40V48_16K]	= "PA-bits:40,  VA-bits:48, 16K pages",  		[VM_MODE_P40V48_64K]	= "PA-bits:40,  VA-bits:48, 64K pages",  		[VM_MODE_PXXV48_4K]	= "PA-bits:ANY, VA-bits:48,  4K pages",  		[VM_MODE_P47V64_4K]	= "PA-bits:47,  VA-bits:64,  4K pages",  		[VM_MODE_P44V64_4K]	= "PA-bits:44,  VA-bits:64,  4K pages", +		[VM_MODE_P36V48_4K]	= "PA-bits:36,  VA-bits:48,  4K pages", +		[VM_MODE_P36V48_16K]	= "PA-bits:36,  VA-bits:48, 16K pages", +		[VM_MODE_P36V48_64K]	= "PA-bits:36,  VA-bits:48, 64K pages", +		[VM_MODE_P36V47_16K]	= "PA-bits:36,  VA-bits:47, 16K pages",  	};  	_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,  		       "Missing new mode strings?"); @@ -185,12 +218,18 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {  	[VM_MODE_P52V48_4K]	= { 52, 48,  0x1000, 12 },  	[VM_MODE_P52V48_64K]	= { 52, 48, 0x10000, 16 },  	[VM_MODE_P48V48_4K]	= { 48, 48,  0x1000, 12 }, +	[VM_MODE_P48V48_16K]	= { 48, 48,  0x4000, 14 },  	[VM_MODE_P48V48_64K]	= { 48, 48, 0x10000, 16 },  	[VM_MODE_P40V48_4K]	= { 40, 48,  0x1000, 12 }, +	[VM_MODE_P40V48_16K]	= { 40, 48,  0x4000, 14 },  	[VM_MODE_P40V48_64K]	= { 40, 48, 0x10000, 16 },  	[VM_MODE_PXXV48_4K]	= {  0,  0,  0x1000, 12 },  	[VM_MODE_P47V64_4K]	= { 47, 64,  0x1000, 12 },  	[VM_MODE_P44V64_4K]	= { 44, 64,  0x1000, 12 }, +	[VM_MODE_P36V48_4K]	= { 36, 48,  0x1000, 12 }, +	[VM_MODE_P36V48_16K]	= { 36, 48,  0x4000, 14 }, +	[VM_MODE_P36V48_64K]	= { 36, 48, 0x10000, 16 }, +	[VM_MODE_P36V47_16K]	= { 36, 47,  0x4000, 14 },  };  _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,  	       "Missing new mode params?"); @@ -252,9 +291,19 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)  		vm->pgtable_levels = 3;  		break;  	case VM_MODE_P40V48_4K: +	case VM_MODE_P36V48_4K:  		vm->pgtable_levels = 4;  		break;  	case VM_MODE_P40V48_64K: +	case VM_MODE_P36V48_64K: +		vm->pgtable_levels = 3; +		break; +	case VM_MODE_P48V48_16K: +	case VM_MODE_P40V48_16K: +	case VM_MODE_P36V48_16K: +		vm->pgtable_levels = 4; +		break; +	case VM_MODE_P36V47_16K:  		vm->pgtable_levels = 3;  		break;  	case VM_MODE_PXXV48_4K: @@ -302,7 +351,7 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)  		(1ULL << (vm->va_bits - 1)) >> vm->page_shift);  	/* Limit physical addresses to PA-bits. */ -	vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; +	vm->max_gfn = vm_compute_max_gfn(vm);  	/* Allocate and setup memory for guest. */  	vm->vpages_mapped = sparsebit_alloc(); @@ -344,6 +393,11 @@ struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus,  	struct kvm_vm *vm;  	int i; +	/* +	 * Permission needs to be requested before KVM_SET_CPUID2. +	 */ +	vm_xsave_req_perm(); +  	/* Force slot0 memory size not small than DEFAULT_GUEST_PHY_PAGES */  	if (slot0_mem_pages < DEFAULT_GUEST_PHY_PAGES)  		slot0_mem_pages = DEFAULT_GUEST_PHY_PAGES; @@ -2087,6 +2141,78 @@ int vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group,  }  /* + * IRQ related functions. + */ + +int _kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level) +{ +	struct kvm_irq_level irq_level = { +		.irq    = irq, +		.level  = level, +	}; + +	return _vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); +} + +void kvm_irq_line(struct kvm_vm *vm, uint32_t irq, int level) +{ +	int ret = _kvm_irq_line(vm, irq, level); + +	TEST_ASSERT(ret >= 0, "KVM_IRQ_LINE failed, rc: %i errno: %i", ret, errno); +} + +struct kvm_irq_routing *kvm_gsi_routing_create(void) +{ +	struct kvm_irq_routing *routing; +	size_t size; + +	size = sizeof(struct kvm_irq_routing); +	/* Allocate space for the max number of entries: this wastes 196 KBs. */ +	size += KVM_MAX_IRQ_ROUTES * sizeof(struct kvm_irq_routing_entry); +	routing = calloc(1, size); +	assert(routing); + +	return routing; +} + +void kvm_gsi_routing_irqchip_add(struct kvm_irq_routing *routing, +		uint32_t gsi, uint32_t pin) +{ +	int i; + +	assert(routing); +	assert(routing->nr < KVM_MAX_IRQ_ROUTES); + +	i = routing->nr; +	routing->entries[i].gsi = gsi; +	routing->entries[i].type = KVM_IRQ_ROUTING_IRQCHIP; +	routing->entries[i].flags = 0; +	routing->entries[i].u.irqchip.irqchip = 0; +	routing->entries[i].u.irqchip.pin = pin; +	routing->nr++; +} + +int _kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing) +{ +	int ret; + +	assert(routing); +	ret = ioctl(vm_get_fd(vm), KVM_SET_GSI_ROUTING, routing); +	free(routing); + +	return ret; +} + +void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing) +{ +	int ret; + +	ret = _kvm_gsi_routing_write(vm, routing); +	TEST_ASSERT(ret == 0, "KVM_SET_GSI_ROUTING failed, rc: %i errno: %i", +				ret, errno); +} + +/*   * VM Dump   *   * Input Args: @@ -2328,6 +2454,11 @@ unsigned int vm_get_page_shift(struct kvm_vm *vm)  	return vm->page_shift;  } +unsigned long __attribute__((weak)) vm_compute_max_gfn(struct kvm_vm *vm) +{ +	return ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; +} +  uint64_t vm_get_max_gfn(struct kvm_vm *vm)  {  	return vm->max_gfn; |