KVM/arm updates for Linux 5.5: - Allow non-ISV data aborts to be reported to userspace - Allow injection of data aborts from userspace - Expose stolen time to guests - GICv4 performance improvements - vgic ITS emulation fixes - Simplify FWB handling - Enable halt pool counters - Make the emulated timer PREEMPT_RT compliant
Showing the changes to include/linux (7 of 55 files). Show all
Unified · Split
| @@ -45,6 +45,7 @@ · 44 unmodified lines | ||
| 45 | 45 | #define ARM_SMCCC_OWNER_SIP 2 |
| 46 | 46 | #define ARM_SMCCC_OWNER_OEM 3 |
| 47 | 47 | #define ARM_SMCCC_OWNER_STANDARD 4 |
| 48 | +#define ARM_SMCCC_OWNER_STANDARD_HYP 5 | |
| 48 | 49 | #define ARM_SMCCC_OWNER_TRUSTED_APP 48 |
| 49 | 50 | #define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 |
| 50 | 51 | #define ARM_SMCCC_OWNER_TRUSTED_OS 50 |
| @@ -80,6 +81,22 @@ · 29 unmodified lines | ||
| 80 | 81 | |
| 81 | 82 | #include <linux/linkage.h> |
| 82 | 83 | #include <linux/types.h> |
| 84 | + | |
| 85 | +enum arm_smccc_conduit { | |
| 86 | + SMCCC_CONDUIT_NONE, | |
| 87 | + SMCCC_CONDUIT_SMC, | |
| 88 | + SMCCC_CONDUIT_HVC, | |
| 89 | +}; | |
| 90 | + | |
| 91 | +/** | |
| 92 | + * arm_smccc_1_1_get_conduit() | |
| 93 | + * | |
| 94 | + * Returns the conduit to be used for SMCCCv1.1 or later. | |
| 95 | + * | |
| 96 | + * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE. | |
| 97 | + */ | |
| 98 | +enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void); | |
| 99 | + | |
| 83 | 100 | /** |
| 84 | 101 | * struct arm_smccc_res - Result from SMC/HVC call |
| 85 | 102 | * @a0-a3 result values from registers 0 to 3 |
| @@ -302,5 +319,63 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, · 216 unmodified lines | ||
| 302 | 319 | #define SMCCC_RET_NOT_SUPPORTED -1 |
| 303 | 320 | #define SMCCC_RET_NOT_REQUIRED -2 |
| 304 | 321 | |
| 322 | +/* | |
| 323 | + * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED. | |
| 324 | + * Used when the SMCCC conduit is not defined. The empty asm statement | |
| 325 | + * avoids compiler warnings about unused variables. | |
| 326 | + */ | |
| 327 | +#define __fail_smccc_1_1(...) \ | |
| 328 | + do { \ | |
| 329 | + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ | |
| 330 | + asm ("" __constraints(__count_args(__VA_ARGS__))); \ | |
| 331 | + if (___res) \ | |
| 332 | + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ | |
| 333 | + } while (0) | |
| 334 | + | |
| 335 | +/* | |
| 336 | + * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call | |
| 337 | + * | |
| 338 | + * This is a variadic macro taking one to eight source arguments, and | |
| 339 | + * an optional return structure. | |
| 340 | + * | |
| 341 | + * @a0-a7: arguments passed in registers 0 to 7 | |
| 342 | + * @res: result values from registers 0 to 3 | |
| 343 | + * | |
| 344 | + * This macro will make either an HVC call or an SMC call depending on the | |
| 345 | + * current SMCCC conduit. If no valid conduit is available then -1 | |
| 346 | + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). | |
| 347 | + * | |
| 348 | + * The return value also provides the conduit that was used. | |
| 349 | + */ | |
| 350 | +#define arm_smccc_1_1_invoke(...) ({ \ | |
| 351 | + int method = arm_smccc_1_1_get_conduit(); \ | |
| 352 | + switch (method) { \ | |
| 353 | + case SMCCC_CONDUIT_HVC: \ | |
| 354 | + arm_smccc_1_1_hvc(__VA_ARGS__); \ | |
| 355 | + break; \ | |
| 356 | + case SMCCC_CONDUIT_SMC: \ | |
| 357 | + arm_smccc_1_1_smc(__VA_ARGS__); \ | |
| 358 | + break; \ | |
| 359 | + default: \ | |
| 360 | + __fail_smccc_1_1(__VA_ARGS__); \ | |
| 361 | + method = SMCCC_CONDUIT_NONE; \ | |
| 362 | + break; \ | |
| 363 | + } \ | |
| 364 | + method; \ | |
| 365 | + }) | |
| 366 | + | |
| 367 | +/* Paravirtualised time calls (defined by ARM DEN0057A) */ | |
| 368 | +#define ARM_SMCCC_HV_PV_TIME_FEATURES \ | |
| 369 | + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ | |
| 370 | + ARM_SMCCC_SMC_64, \ | |
| 371 | + ARM_SMCCC_OWNER_STANDARD_HYP, \ | |
| 372 | + 0x20) | |
| 373 | + | |
| 374 | +#define ARM_SMCCC_HV_PV_TIME_ST \ | |
| 375 | + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ | |
| 376 | + ARM_SMCCC_SMC_64, \ | |
| 377 | + ARM_SMCCC_OWNER_STANDARD_HYP, \ | |
| 378 | + 0x21) | |
| 379 | + | |
| 305 | 380 | #endif /*__ASSEMBLY__*/ |
| 306 | 381 | #endif /*__LINUX_ARM_SMCCC_H*/ |
| @@ -5,12 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include <uapi/linux/arm_sdei.h> |
| 7 | 7 | |
| 8 | −enum sdei_conduit_types { | |
| 9 | − CONDUIT_INVALID = 0, | |
| 10 | − CONDUIT_SMC, | |
| 11 | − CONDUIT_HVC, | |
| 12 | −}; | |
| 13 | − | |
| 14 | 8 | #include <acpi/ghes.h> |
| 15 | 9 | |
| 16 | 10 | #ifdef CONFIG_ARM_SDE_INTERFACE |
| @@ -136,6 +136,7 @@ enum cpuhp_state { · 135 unmodified lines | ||
| 136 | 136 | /* Must be the last timer callback */ |
| 137 | 137 | CPUHP_AP_DUMMY_TIMER_STARTING, |
| 138 | 138 | CPUHP_AP_ARM_XEN_STARTING, |
| 139 | + CPUHP_AP_ARM_KVMPV_STARTING, | |
| 139 | 140 | CPUHP_AP_ARM_CORESIGHT_STARTING, |
| 140 | 141 | CPUHP_AP_ARM64_ISNDEP_STARTING, |
| 141 | 142 | CPUHP_AP_SMPCFD_DYING, |
| @@ -32,9 +32,13 @@ struct its_vm { · 31 unmodified lines | ||
| 32 | 32 | struct its_vpe { |
| 33 | 33 | struct page *vpt_page; |
| 34 | 34 | struct its_vm *its_vm; |
| 35 | + /* per-vPE VLPI tracking */ | |
| 36 | + atomic_t vlpi_count; | |
| 35 | 37 | /* Doorbell interrupt */ |
| 36 | 38 | int irq; |
| 37 | 39 | irq_hw_number_t vpe_db_lpi; |
| 40 | + /* VPE resident */ | |
| 41 | + bool resident; | |
| 38 | 42 | /* VPE proxy mapping */ |
| 39 | 43 | int vpe_proxy_event; |
| 40 | 44 | /* |
| @@ -741,6 +741,28 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, · 740 unmodified lines | ||
| 741 | 741 | unsigned long len); |
| 742 | 742 | int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, |
| 743 | 743 | gpa_t gpa, unsigned long len); |
| 744 | + | |
| 745 | +#define __kvm_put_guest(kvm, gfn, offset, value, type) \ | |
| 746 | +({ \ | |
| 747 | + unsigned long __addr = gfn_to_hva(kvm, gfn); \ | |
| 748 | + type __user *__uaddr = (type __user *)(__addr + offset); \ | |
| 749 | + int __ret = -EFAULT; \ | |
| 750 | + \ | |
| 751 | + if (!kvm_is_error_hva(__addr)) \ | |
| 752 | + __ret = put_user(value, __uaddr); \ | |
| 753 | + if (!__ret) \ | |
| 754 | + mark_page_dirty(kvm, gfn); \ | |
| 755 | + __ret; \ | |
| 756 | +}) | |
| 757 | + | |
| 758 | +#define kvm_put_guest(kvm, gpa, value, type) \ | |
| 759 | +({ \ | |
| 760 | + gpa_t __gpa = gpa; \ | |
| 761 | + struct kvm *__kvm = kvm; \ | |
| 762 | + __kvm_put_guest(__kvm, __gpa >> PAGE_SHIFT, \ | |
| 763 | + offset_in_page(__gpa), (value), type); \ | |
| 764 | +}) | |
| 765 | + | |
| 744 | 766 | int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); |
| 745 | 767 | int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); |
| 746 | 768 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); |
| @@ -1237,7 +1259,7 @@ extern unsigned int halt_poll_ns_grow_start; · 490 unmodified lines | ||
| 1237 | 1259 | extern unsigned int halt_poll_ns_shrink; |
| 1238 | 1260 | |
| 1239 | 1261 | struct kvm_device { |
| 1240 | − struct kvm_device_ops *ops; | |
| 1262 | + const struct kvm_device_ops *ops; | |
| 1241 | 1263 | struct kvm *kvm; |
| 1242 | 1264 | void *private; |
| 1243 | 1265 | struct list_head vm_node; |
| @@ -1290,7 +1312,7 @@ struct kvm_device_ops { · 46 unmodified lines | ||
| 1290 | 1312 | void kvm_device_get(struct kvm_device *dev); |
| 1291 | 1313 | void kvm_device_put(struct kvm_device *dev); |
| 1292 | 1314 | struct kvm_device *kvm_device_from_filp(struct file *filp); |
| 1293 | −int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type); | |
| 1315 | +int kvm_register_device_ops(const struct kvm_device_ops *ops, u32 type); | |
| 1294 | 1316 | void kvm_unregister_device_ops(u32 type); |
| 1295 | 1317 | |
| 1296 | 1318 | extern struct kvm_device_ops kvm_mpic_ops; |
| @@ -35,6 +35,8 @@ typedef unsigned long gva_t; · 34 unmodified lines | ||
| 35 | 35 | typedef u64 gpa_t; |
| 36 | 36 | typedef u64 gfn_t; |
| 37 | 37 | |
| 38 | +#define GPA_INVALID (~(gpa_t)0) | |
| 39 | + | |
| 38 | 40 | typedef unsigned long hva_t; |
| 39 | 41 | typedef u64 hpa_t; |
| 40 | 42 | typedef u64 hfn_t; |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #ifndef __LINUX_PSCI_H |
| 8 | 8 | #define __LINUX_PSCI_H |
| 9 | 9 | |
| 10 | +#include <linux/arm-smccc.h> | |
| 10 | 11 | #include <linux/init.h> |
| 11 | 12 | #include <linux/types.h> |
| 12 | 13 | |
| @@ -18,12 +19,6 @@ bool psci_tos_resident_on(int cpu); · 5 unmodified lines | ||
| 18 | 19 | int psci_cpu_suspend_enter(u32 state); |
| 19 | 20 | bool psci_power_state_is_valid(u32 state); |
| 20 | 21 | |
| 21 | −enum psci_conduit { | |
| 22 | − PSCI_CONDUIT_NONE, | |
| 23 | − PSCI_CONDUIT_SMC, | |
| 24 | − PSCI_CONDUIT_HVC, | |
| 25 | −}; | |
| 26 | − | |
| 27 | 22 | enum smccc_version { |
| 28 | 23 | SMCCC_VERSION_1_0, |
| 29 | 24 | SMCCC_VERSION_1_1, |
| @@ -38,7 +33,7 @@ struct psci_operations { · 8 unmodified lines | ||
| 38 | 33 | int (*affinity_info)(unsigned long target_affinity, |
| 39 | 34 | unsigned long lowest_affinity_level); |
| 40 | 35 | int (*migrate_info_type)(void); |
| 41 | − enum psci_conduit conduit; | |
| 36 | + enum arm_smccc_conduit conduit; | |
| 42 | 37 | enum smccc_version smccc_version; |
| 43 | 38 | }; |
| 44 | 39 | |