diff options
author | Eric Auger <eric.auger@redhat.com> | 2017-10-26 11:23:11 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2017-11-06 10:23:19 -0500 |
commit | 3eb4271b4ab6d38a3c113a19f358f606702e08ef (patch) | |
tree | fff5da9bc0f0fb5cb4403bda552648bda4b1a84b | |
parent | ae204f80ca4074b6db07bd28c75faf02718735a0 (diff) |
KVM: arm/arm64: vgic-its: Implement KVM_DEV_ARM_ITS_CTRL_RESET
On reset we clear the valid bits of GITS_CBASER and GITS_BASER<n>.
We also clear command queue registers and free the cache (device,
collection, and lpi lists).
As we need to take the same locks as save/restore functions, we
create a vgic_its_ctrl() wrapper that handles KVM_DEV_ARM_VGIC_GRP_CTRL
group functions.
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 1 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/kvm.h | 1 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 105 |
3 files changed, 58 insertions, 49 deletions
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 665c454e50d0..b56895593c84 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h | |||
@@ -221,6 +221,7 @@ struct kvm_arch_memory_slot { | |||
221 | #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 | 221 | #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 |
222 | #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 | 222 | #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 |
223 | #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 | 223 | #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 |
224 | #define KVM_DEV_ARM_ITS_CTRL_RESET 4 | ||
224 | 225 | ||
225 | /* KVM_IRQ_LINE irq field index values */ | 226 | /* KVM_IRQ_LINE irq field index values */ |
226 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 | 227 | #define KVM_ARM_IRQ_TYPE_SHIFT 24 |
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 0004feef7cc2..37ca7394549c 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h | |||
@@ -233,6 +233,7 @@ struct kvm_arch_memory_slot { | |||
233 | #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 | 233 | #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 |
234 | #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 | 234 | #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 |
235 | #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 | 235 | #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 |
236 | #define KVM_DEV_ARM_ITS_CTRL_RESET 4 | ||
236 | 237 | ||
237 | /* Device Control API on vcpu fd */ | 238 | /* Device Control API on vcpu fd */ |
238 | #define KVM_ARM_VCPU_PMU_V3_CTRL 0 | 239 | #define KVM_ARM_VCPU_PMU_V3_CTRL 0 |
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 1732e08a4375..40791c121710 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
@@ -2273,29 +2273,13 @@ static int vgic_its_restore_collection_table(struct vgic_its *its) | |||
2273 | */ | 2273 | */ |
2274 | static int vgic_its_save_tables_v0(struct vgic_its *its) | 2274 | static int vgic_its_save_tables_v0(struct vgic_its *its) |
2275 | { | 2275 | { |
2276 | struct kvm *kvm = its->dev->kvm; | ||
2277 | int ret; | 2276 | int ret; |
2278 | 2277 | ||
2279 | mutex_lock(&kvm->lock); | ||
2280 | mutex_lock(&its->its_lock); | ||
2281 | |||
2282 | if (!lock_all_vcpus(kvm)) { | ||
2283 | mutex_unlock(&its->its_lock); | ||
2284 | mutex_unlock(&kvm->lock); | ||
2285 | return -EBUSY; | ||
2286 | } | ||
2287 | |||
2288 | ret = vgic_its_save_device_tables(its); | 2278 | ret = vgic_its_save_device_tables(its); |
2289 | if (ret) | 2279 | if (ret) |
2290 | goto out; | 2280 | return ret; |
2291 | |||
2292 | ret = vgic_its_save_collection_table(its); | ||
2293 | 2281 | ||
2294 | out: | 2282 | return vgic_its_save_collection_table(its); |
2295 | unlock_all_vcpus(kvm); | ||
2296 | mutex_unlock(&its->its_lock); | ||
2297 | mutex_unlock(&kvm->lock); | ||
2298 | return ret; | ||
2299 | } | 2283 | } |
2300 | 2284 | ||
2301 | /** | 2285 | /** |
@@ -2305,29 +2289,13 @@ out: | |||
2305 | */ | 2289 | */ |
2306 | static int vgic_its_restore_tables_v0(struct vgic_its *its) | 2290 | static int vgic_its_restore_tables_v0(struct vgic_its *its) |
2307 | { | 2291 | { |
2308 | struct kvm *kvm = its->dev->kvm; | ||
2309 | int ret; | 2292 | int ret; |
2310 | 2293 | ||
2311 | mutex_lock(&kvm->lock); | ||
2312 | mutex_lock(&its->its_lock); | ||
2313 | |||
2314 | if (!lock_all_vcpus(kvm)) { | ||
2315 | mutex_unlock(&its->its_lock); | ||
2316 | mutex_unlock(&kvm->lock); | ||
2317 | return -EBUSY; | ||
2318 | } | ||
2319 | |||
2320 | ret = vgic_its_restore_collection_table(its); | 2294 | ret = vgic_its_restore_collection_table(its); |
2321 | if (ret) | 2295 | if (ret) |
2322 | goto out; | 2296 | return ret; |
2323 | |||
2324 | ret = vgic_its_restore_device_tables(its); | ||
2325 | out: | ||
2326 | unlock_all_vcpus(kvm); | ||
2327 | mutex_unlock(&its->its_lock); | ||
2328 | mutex_unlock(&kvm->lock); | ||
2329 | 2297 | ||
2330 | return ret; | 2298 | return vgic_its_restore_device_tables(its); |
2331 | } | 2299 | } |
2332 | 2300 | ||
2333 | static int vgic_its_commit_v0(struct vgic_its *its) | 2301 | static int vgic_its_commit_v0(struct vgic_its *its) |
@@ -2346,6 +2314,19 @@ static int vgic_its_commit_v0(struct vgic_its *its) | |||
2346 | return 0; | 2314 | return 0; |
2347 | } | 2315 | } |
2348 | 2316 | ||
2317 | static void vgic_its_reset(struct kvm *kvm, struct vgic_its *its) | ||
2318 | { | ||
2319 | /* We need to keep the ABI specific field values */ | ||
2320 | its->baser_coll_table &= ~GITS_BASER_VALID; | ||
2321 | its->baser_device_table &= ~GITS_BASER_VALID; | ||
2322 | its->cbaser = 0; | ||
2323 | its->creadr = 0; | ||
2324 | its->cwriter = 0; | ||
2325 | its->enabled = 0; | ||
2326 | vgic_its_free_device_list(kvm, its); | ||
2327 | vgic_its_free_collection_list(kvm, its); | ||
2328 | } | ||
2329 | |||
2349 | static int vgic_its_has_attr(struct kvm_device *dev, | 2330 | static int vgic_its_has_attr(struct kvm_device *dev, |
2350 | struct kvm_device_attr *attr) | 2331 | struct kvm_device_attr *attr) |
2351 | { | 2332 | { |
@@ -2360,6 +2341,8 @@ static int vgic_its_has_attr(struct kvm_device *dev, | |||
2360 | switch (attr->attr) { | 2341 | switch (attr->attr) { |
2361 | case KVM_DEV_ARM_VGIC_CTRL_INIT: | 2342 | case KVM_DEV_ARM_VGIC_CTRL_INIT: |
2362 | return 0; | 2343 | return 0; |
2344 | case KVM_DEV_ARM_ITS_CTRL_RESET: | ||
2345 | return 0; | ||
2363 | case KVM_DEV_ARM_ITS_SAVE_TABLES: | 2346 | case KVM_DEV_ARM_ITS_SAVE_TABLES: |
2364 | return 0; | 2347 | return 0; |
2365 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: | 2348 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: |
@@ -2372,6 +2355,41 @@ static int vgic_its_has_attr(struct kvm_device *dev, | |||
2372 | return -ENXIO; | 2355 | return -ENXIO; |
2373 | } | 2356 | } |
2374 | 2357 | ||
2358 | static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) | ||
2359 | { | ||
2360 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | ||
2361 | int ret = 0; | ||
2362 | |||
2363 | if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */ | ||
2364 | return 0; | ||
2365 | |||
2366 | mutex_lock(&kvm->lock); | ||
2367 | mutex_lock(&its->its_lock); | ||
2368 | |||
2369 | if (!lock_all_vcpus(kvm)) { | ||
2370 | mutex_unlock(&its->its_lock); | ||
2371 | mutex_unlock(&kvm->lock); | ||
2372 | return -EBUSY; | ||
2373 | } | ||
2374 | |||
2375 | switch (attr) { | ||
2376 | case KVM_DEV_ARM_ITS_CTRL_RESET: | ||
2377 | vgic_its_reset(kvm, its); | ||
2378 | break; | ||
2379 | case KVM_DEV_ARM_ITS_SAVE_TABLES: | ||
2380 | ret = abi->save_tables(its); | ||
2381 | break; | ||
2382 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: | ||
2383 | ret = abi->restore_tables(its); | ||
2384 | break; | ||
2385 | } | ||
2386 | |||
2387 | unlock_all_vcpus(kvm); | ||
2388 | mutex_unlock(&its->its_lock); | ||
2389 | mutex_unlock(&kvm->lock); | ||
2390 | return ret; | ||
2391 | } | ||
2392 | |||
2375 | static int vgic_its_set_attr(struct kvm_device *dev, | 2393 | static int vgic_its_set_attr(struct kvm_device *dev, |
2376 | struct kvm_device_attr *attr) | 2394 | struct kvm_device_attr *attr) |
2377 | { | 2395 | { |
@@ -2397,19 +2415,8 @@ static int vgic_its_set_attr(struct kvm_device *dev, | |||
2397 | 2415 | ||
2398 | return vgic_register_its_iodev(dev->kvm, its, addr); | 2416 | return vgic_register_its_iodev(dev->kvm, its, addr); |
2399 | } | 2417 | } |
2400 | case KVM_DEV_ARM_VGIC_GRP_CTRL: { | 2418 | case KVM_DEV_ARM_VGIC_GRP_CTRL: |
2401 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 2419 | return vgic_its_ctrl(dev->kvm, its, attr->attr); |
2402 | |||
2403 | switch (attr->attr) { | ||
2404 | case KVM_DEV_ARM_VGIC_CTRL_INIT: | ||
2405 | /* Nothing to do */ | ||
2406 | return 0; | ||
2407 | case KVM_DEV_ARM_ITS_SAVE_TABLES: | ||
2408 | return abi->save_tables(its); | ||
2409 | case KVM_DEV_ARM_ITS_RESTORE_TABLES: | ||
2410 | return abi->restore_tables(its); | ||
2411 | } | ||
2412 | } | ||
2413 | case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: { | 2420 | case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: { |
2414 | u64 __user *uaddr = (u64 __user *)(long)attr->addr; | 2421 | u64 __user *uaddr = (u64 __user *)(long)attr->addr; |
2415 | u64 reg; | 2422 | u64 reg; |