diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-04 14:44:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-04 14:44:55 -0400 |
| commit | f0a32ee42f73a7e6229d6dd68d222a507447acd7 (patch) | |
| tree | fdd2e2185ab8b37b60b0f469169e4c75abb1538f | |
| parent | b1878b857c732830ec38204196f99e4236b57b6e (diff) | |
| parent | b33c87328364e803d74e703d8e47821740dbfa87 (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fixes from Paolo Bonzini:
"Fixes for interrupt controller emulation in ARM/ARM64 and x86, plus a
one-liner x86 KVM guest fix"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: x86: Update APICv on APIC reset
KVM: VMX: Do not fully reset PI descriptor on vCPU reset
kvm: Return -ENODEV from update_persistent_clock
KVM: arm/arm64: vgic-its: Check GITS_BASER Valid bit before saving tables
KVM: arm/arm64: vgic-its: Check CBASER/BASER validity before enabling the ITS
KVM: arm/arm64: vgic-its: Fix vgic_its_restore_collection_table returned value
KVM: arm/arm64: vgic-its: Fix return value for device table restore
arm/arm64: kvm: Disable branch profiling in HYP code
arm/arm64: kvm: Move initialization completion message
arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort
KVM: arm64: its: Fix missing dynamic allocation check in scan_its_table
| -rw-r--r-- | arch/arm/kvm/emulate.c | 6 | ||||
| -rw-r--r-- | arch/arm/kvm/hyp/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm64/kvm/hyp/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm64/kvm/inject_fault.c | 16 | ||||
| -rw-r--r-- | arch/x86/kernel/kvmclock.c | 2 | ||||
| -rw-r--r-- | arch/x86/kvm/lapic.c | 5 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx.c | 3 | ||||
| -rw-r--r-- | virt/kvm/arm/arm.c | 31 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 73 |
9 files changed, 87 insertions, 53 deletions
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 0064b86a2c87..30a13647c54c 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c | |||
| @@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) | |||
| 227 | u32 return_offset = (is_thumb) ? 2 : 4; | 227 | u32 return_offset = (is_thumb) ? 2 : 4; |
| 228 | 228 | ||
| 229 | kvm_update_psr(vcpu, UND_MODE); | 229 | kvm_update_psr(vcpu, UND_MODE); |
| 230 | *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset; | 230 | *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; |
| 231 | 231 | ||
| 232 | /* Branch to exception vector */ | 232 | /* Branch to exception vector */ |
| 233 | *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; | 233 | *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; |
| @@ -239,10 +239,8 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) | |||
| 239 | */ | 239 | */ |
| 240 | static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) | 240 | static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) |
| 241 | { | 241 | { |
| 242 | unsigned long cpsr = *vcpu_cpsr(vcpu); | ||
| 243 | bool is_thumb = (cpsr & PSR_T_BIT); | ||
| 244 | u32 vect_offset; | 242 | u32 vect_offset; |
| 245 | u32 return_offset = (is_thumb) ? 4 : 0; | 243 | u32 return_offset = (is_pabt) ? 4 : 8; |
| 246 | bool is_lpae; | 244 | bool is_lpae; |
| 247 | 245 | ||
| 248 | kvm_update_psr(vcpu, ABT_MODE); | 246 | kvm_update_psr(vcpu, ABT_MODE); |
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile index 5fca24d52fe6..5638ce0c9524 100644 --- a/arch/arm/kvm/hyp/Makefile +++ b/arch/arm/kvm/hyp/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # Makefile for Kernel-based Virtual Machine module, HYP part | 3 | # Makefile for Kernel-based Virtual Machine module, HYP part |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | ccflags-y += -fno-stack-protector | 6 | ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING |
| 7 | 7 | ||
| 8 | KVM=../../../../virt/kvm | 8 | KVM=../../../../virt/kvm |
| 9 | 9 | ||
diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 7c54d8fde855..f04400d494b7 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # Makefile for Kernel-based Virtual Machine module, HYP part | 3 | # Makefile for Kernel-based Virtual Machine module, HYP part |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | ccflags-y += -fno-stack-protector | 6 | ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING |
| 7 | 7 | ||
| 8 | KVM=../../../../virt/kvm | 8 | KVM=../../../../virt/kvm |
| 9 | 9 | ||
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index da6a8cfa54a0..3556715a774e 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c | |||
| @@ -33,12 +33,26 @@ | |||
| 33 | #define LOWER_EL_AArch64_VECTOR 0x400 | 33 | #define LOWER_EL_AArch64_VECTOR 0x400 |
| 34 | #define LOWER_EL_AArch32_VECTOR 0x600 | 34 | #define LOWER_EL_AArch32_VECTOR 0x600 |
| 35 | 35 | ||
| 36 | /* | ||
| 37 | * Table taken from ARMv8 ARM DDI0487B-B, table G1-10. | ||
| 38 | */ | ||
| 39 | static const u8 return_offsets[8][2] = { | ||
| 40 | [0] = { 0, 0 }, /* Reset, unused */ | ||
| 41 | [1] = { 4, 2 }, /* Undefined */ | ||
| 42 | [2] = { 0, 0 }, /* SVC, unused */ | ||
| 43 | [3] = { 4, 4 }, /* Prefetch abort */ | ||
| 44 | [4] = { 8, 8 }, /* Data abort */ | ||
| 45 | [5] = { 0, 0 }, /* HVC, unused */ | ||
| 46 | [6] = { 4, 4 }, /* IRQ, unused */ | ||
| 47 | [7] = { 4, 4 }, /* FIQ, unused */ | ||
| 48 | }; | ||
| 49 | |||
| 36 | static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) | 50 | static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) |
| 37 | { | 51 | { |
| 38 | unsigned long cpsr; | 52 | unsigned long cpsr; |
| 39 | unsigned long new_spsr_value = *vcpu_cpsr(vcpu); | 53 | unsigned long new_spsr_value = *vcpu_cpsr(vcpu); |
| 40 | bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT); | 54 | bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT); |
| 41 | u32 return_offset = (is_thumb) ? 4 : 0; | 55 | u32 return_offset = return_offsets[vect_offset >> 2][is_thumb]; |
| 42 | u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); | 56 | u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); |
| 43 | 57 | ||
| 44 | cpsr = mode | COMPAT_PSR_I_BIT; | 58 | cpsr = mode | COMPAT_PSR_I_BIT; |
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index d88967659098..5b609e28ce3f 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
| @@ -79,7 +79,7 @@ static void kvm_get_wallclock(struct timespec *now) | |||
| 79 | 79 | ||
| 80 | static int kvm_set_wallclock(const struct timespec *now) | 80 | static int kvm_set_wallclock(const struct timespec *now) |
| 81 | { | 81 | { |
| 82 | return -1; | 82 | return -ENODEV; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static u64 kvm_clock_read(void) | 85 | static u64 kvm_clock_read(void) |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 69c5612be786..36c90d631096 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
| @@ -1992,6 +1992,11 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) | |||
| 1992 | vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP); | 1992 | vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP); |
| 1993 | vcpu->arch.pv_eoi.msr_val = 0; | 1993 | vcpu->arch.pv_eoi.msr_val = 0; |
| 1994 | apic_update_ppr(apic); | 1994 | apic_update_ppr(apic); |
| 1995 | if (vcpu->arch.apicv_active) { | ||
| 1996 | kvm_x86_ops->apicv_post_state_restore(vcpu); | ||
| 1997 | kvm_x86_ops->hwapic_irr_update(vcpu, -1); | ||
| 1998 | kvm_x86_ops->hwapic_isr_update(vcpu, -1); | ||
| 1999 | } | ||
| 1995 | 2000 | ||
| 1996 | vcpu->arch.apic_arb_prio = 0; | 2001 | vcpu->arch.apic_arb_prio = 0; |
| 1997 | vcpu->arch.apic_attention = 0; | 2002 | vcpu->arch.apic_attention = 0; |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 95a01609d7ee..a6f4f095f8f4 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -5619,9 +5619,6 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) | |||
| 5619 | 5619 | ||
| 5620 | kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); | 5620 | kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); |
| 5621 | 5621 | ||
| 5622 | if (kvm_vcpu_apicv_active(vcpu)) | ||
| 5623 | memset(&vmx->pi_desc, 0, sizeof(struct pi_desc)); | ||
| 5624 | |||
| 5625 | if (vmx->vpid != 0) | 5622 | if (vmx->vpid != 0) |
| 5626 | vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); | 5623 | vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); |
| 5627 | 5624 | ||
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index b9f68e4add71..95cba0799828 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c | |||
| @@ -1326,21 +1326,12 @@ static void teardown_hyp_mode(void) | |||
| 1326 | { | 1326 | { |
| 1327 | int cpu; | 1327 | int cpu; |
| 1328 | 1328 | ||
| 1329 | if (is_kernel_in_hyp_mode()) | ||
| 1330 | return; | ||
| 1331 | |||
| 1332 | free_hyp_pgds(); | 1329 | free_hyp_pgds(); |
| 1333 | for_each_possible_cpu(cpu) | 1330 | for_each_possible_cpu(cpu) |
| 1334 | free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); | 1331 | free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); |
| 1335 | hyp_cpu_pm_exit(); | 1332 | hyp_cpu_pm_exit(); |
| 1336 | } | 1333 | } |
| 1337 | 1334 | ||
| 1338 | static int init_vhe_mode(void) | ||
| 1339 | { | ||
| 1340 | kvm_info("VHE mode initialized successfully\n"); | ||
| 1341 | return 0; | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | /** | 1335 | /** |
| 1345 | * Inits Hyp-mode on all online CPUs | 1336 | * Inits Hyp-mode on all online CPUs |
| 1346 | */ | 1337 | */ |
| @@ -1421,8 +1412,6 @@ static int init_hyp_mode(void) | |||
| 1421 | } | 1412 | } |
| 1422 | } | 1413 | } |
| 1423 | 1414 | ||
| 1424 | kvm_info("Hyp mode initialized successfully\n"); | ||
| 1425 | |||
| 1426 | return 0; | 1415 | return 0; |
| 1427 | 1416 | ||
| 1428 | out_err: | 1417 | out_err: |
| @@ -1456,6 +1445,7 @@ int kvm_arch_init(void *opaque) | |||
| 1456 | { | 1445 | { |
| 1457 | int err; | 1446 | int err; |
| 1458 | int ret, cpu; | 1447 | int ret, cpu; |
| 1448 | bool in_hyp_mode; | ||
| 1459 | 1449 | ||
| 1460 | if (!is_hyp_mode_available()) { | 1450 | if (!is_hyp_mode_available()) { |
| 1461 | kvm_err("HYP mode not available\n"); | 1451 | kvm_err("HYP mode not available\n"); |
| @@ -1474,21 +1464,28 @@ int kvm_arch_init(void *opaque) | |||
| 1474 | if (err) | 1464 | if (err) |
| 1475 | return err; | 1465 | return err; |
| 1476 | 1466 | ||
| 1477 | if (is_kernel_in_hyp_mode()) | 1467 | in_hyp_mode = is_kernel_in_hyp_mode(); |
| 1478 | err = init_vhe_mode(); | 1468 | |
| 1479 | else | 1469 | if (!in_hyp_mode) { |
| 1480 | err = init_hyp_mode(); | 1470 | err = init_hyp_mode(); |
| 1481 | if (err) | 1471 | if (err) |
| 1482 | goto out_err; | 1472 | goto out_err; |
| 1473 | } | ||
| 1483 | 1474 | ||
| 1484 | err = init_subsystems(); | 1475 | err = init_subsystems(); |
| 1485 | if (err) | 1476 | if (err) |
| 1486 | goto out_hyp; | 1477 | goto out_hyp; |
| 1487 | 1478 | ||
| 1479 | if (in_hyp_mode) | ||
| 1480 | kvm_info("VHE mode initialized successfully\n"); | ||
| 1481 | else | ||
| 1482 | kvm_info("Hyp mode initialized successfully\n"); | ||
| 1483 | |||
| 1488 | return 0; | 1484 | return 0; |
| 1489 | 1485 | ||
| 1490 | out_hyp: | 1486 | out_hyp: |
| 1491 | teardown_hyp_mode(); | 1487 | if (!in_hyp_mode) |
| 1488 | teardown_hyp_mode(); | ||
| 1492 | out_err: | 1489 | out_err: |
| 1493 | teardown_common_resources(); | 1490 | teardown_common_resources(); |
| 1494 | return err; | 1491 | return err; |
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index f51c1e1b3f70..547f12dc4d54 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
| @@ -1466,6 +1466,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, | |||
| 1466 | { | 1466 | { |
| 1467 | mutex_lock(&its->cmd_lock); | 1467 | mutex_lock(&its->cmd_lock); |
| 1468 | 1468 | ||
| 1469 | /* | ||
| 1470 | * It is UNPREDICTABLE to enable the ITS if any of the CBASER or | ||
| 1471 | * device/collection BASER are invalid | ||
| 1472 | */ | ||
| 1473 | if (!its->enabled && (val & GITS_CTLR_ENABLE) && | ||
| 1474 | (!(its->baser_device_table & GITS_BASER_VALID) || | ||
| 1475 | !(its->baser_coll_table & GITS_BASER_VALID) || | ||
| 1476 | !(its->cbaser & GITS_CBASER_VALID))) | ||
| 1477 | goto out; | ||
| 1478 | |||
| 1469 | its->enabled = !!(val & GITS_CTLR_ENABLE); | 1479 | its->enabled = !!(val & GITS_CTLR_ENABLE); |
| 1470 | 1480 | ||
| 1471 | /* | 1481 | /* |
| @@ -1474,6 +1484,7 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, | |||
| 1474 | */ | 1484 | */ |
| 1475 | vgic_its_process_commands(kvm, its); | 1485 | vgic_its_process_commands(kvm, its); |
| 1476 | 1486 | ||
| 1487 | out: | ||
| 1477 | mutex_unlock(&its->cmd_lock); | 1488 | mutex_unlock(&its->cmd_lock); |
| 1478 | } | 1489 | } |
| 1479 | 1490 | ||
| @@ -1801,37 +1812,33 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry, | |||
| 1801 | static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz, | 1812 | static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz, |
| 1802 | int start_id, entry_fn_t fn, void *opaque) | 1813 | int start_id, entry_fn_t fn, void *opaque) |
| 1803 | { | 1814 | { |
| 1804 | void *entry = kzalloc(esz, GFP_KERNEL); | ||
| 1805 | struct kvm *kvm = its->dev->kvm; | 1815 | struct kvm *kvm = its->dev->kvm; |
| 1806 | unsigned long len = size; | 1816 | unsigned long len = size; |
| 1807 | int id = start_id; | 1817 | int id = start_id; |
| 1808 | gpa_t gpa = base; | 1818 | gpa_t gpa = base; |
| 1819 | char entry[esz]; | ||
| 1809 | int ret; | 1820 | int ret; |
| 1810 | 1821 | ||
| 1822 | memset(entry, 0, esz); | ||
| 1823 | |||
| 1811 | while (len > 0) { | 1824 | while (len > 0) { |
| 1812 | int next_offset; | 1825 | int next_offset; |
| 1813 | size_t byte_offset; | 1826 | size_t byte_offset; |
| 1814 | 1827 | ||
| 1815 | ret = kvm_read_guest(kvm, gpa, entry, esz); | 1828 | ret = kvm_read_guest(kvm, gpa, entry, esz); |
| 1816 | if (ret) | 1829 | if (ret) |
| 1817 | goto out; | 1830 | return ret; |
| 1818 | 1831 | ||
| 1819 | next_offset = fn(its, id, entry, opaque); | 1832 | next_offset = fn(its, id, entry, opaque); |
| 1820 | if (next_offset <= 0) { | 1833 | if (next_offset <= 0) |
| 1821 | ret = next_offset; | 1834 | return next_offset; |
| 1822 | goto out; | ||
| 1823 | } | ||
| 1824 | 1835 | ||
| 1825 | byte_offset = next_offset * esz; | 1836 | byte_offset = next_offset * esz; |
| 1826 | id += next_offset; | 1837 | id += next_offset; |
| 1827 | gpa += byte_offset; | 1838 | gpa += byte_offset; |
| 1828 | len -= byte_offset; | 1839 | len -= byte_offset; |
| 1829 | } | 1840 | } |
| 1830 | ret = 1; | 1841 | return 1; |
| 1831 | |||
| 1832 | out: | ||
| 1833 | kfree(entry); | ||
| 1834 | return ret; | ||
| 1835 | } | 1842 | } |
| 1836 | 1843 | ||
| 1837 | /** | 1844 | /** |
| @@ -1940,6 +1947,14 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device) | |||
| 1940 | return 0; | 1947 | return 0; |
| 1941 | } | 1948 | } |
| 1942 | 1949 | ||
| 1950 | /** | ||
| 1951 | * vgic_its_restore_itt - restore the ITT of a device | ||
| 1952 | * | ||
| 1953 | * @its: its handle | ||
| 1954 | * @dev: device handle | ||
| 1955 | * | ||
| 1956 | * Return 0 on success, < 0 on error | ||
| 1957 | */ | ||
| 1943 | static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) | 1958 | static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) |
| 1944 | { | 1959 | { |
| 1945 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 1960 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| @@ -1951,6 +1966,10 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) | |||
| 1951 | ret = scan_its_table(its, base, max_size, ite_esz, 0, | 1966 | ret = scan_its_table(its, base, max_size, ite_esz, 0, |
| 1952 | vgic_its_restore_ite, dev); | 1967 | vgic_its_restore_ite, dev); |
| 1953 | 1968 | ||
| 1969 | /* scan_its_table returns +1 if all ITEs are invalid */ | ||
| 1970 | if (ret > 0) | ||
| 1971 | ret = 0; | ||
| 1972 | |||
| 1954 | return ret; | 1973 | return ret; |
| 1955 | } | 1974 | } |
| 1956 | 1975 | ||
| @@ -2048,11 +2067,12 @@ static int vgic_its_device_cmp(void *priv, struct list_head *a, | |||
| 2048 | static int vgic_its_save_device_tables(struct vgic_its *its) | 2067 | static int vgic_its_save_device_tables(struct vgic_its *its) |
| 2049 | { | 2068 | { |
| 2050 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 2069 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| 2070 | u64 baser = its->baser_device_table; | ||
| 2051 | struct its_device *dev; | 2071 | struct its_device *dev; |
| 2052 | int dte_esz = abi->dte_esz; | 2072 | int dte_esz = abi->dte_esz; |
| 2053 | u64 baser; | ||
| 2054 | 2073 | ||
| 2055 | baser = its->baser_device_table; | 2074 | if (!(baser & GITS_BASER_VALID)) |
| 2075 | return 0; | ||
| 2056 | 2076 | ||
| 2057 | list_sort(NULL, &its->device_list, vgic_its_device_cmp); | 2077 | list_sort(NULL, &its->device_list, vgic_its_device_cmp); |
| 2058 | 2078 | ||
| @@ -2107,10 +2127,7 @@ static int handle_l1_dte(struct vgic_its *its, u32 id, void *addr, | |||
| 2107 | ret = scan_its_table(its, gpa, SZ_64K, dte_esz, | 2127 | ret = scan_its_table(its, gpa, SZ_64K, dte_esz, |
| 2108 | l2_start_id, vgic_its_restore_dte, NULL); | 2128 | l2_start_id, vgic_its_restore_dte, NULL); |
| 2109 | 2129 | ||
| 2110 | if (ret <= 0) | 2130 | return ret; |
| 2111 | return ret; | ||
| 2112 | |||
| 2113 | return 1; | ||
| 2114 | } | 2131 | } |
| 2115 | 2132 | ||
| 2116 | /** | 2133 | /** |
| @@ -2140,8 +2157,9 @@ static int vgic_its_restore_device_tables(struct vgic_its *its) | |||
| 2140 | vgic_its_restore_dte, NULL); | 2157 | vgic_its_restore_dte, NULL); |
| 2141 | } | 2158 | } |
| 2142 | 2159 | ||
| 2160 | /* scan_its_table returns +1 if all entries are invalid */ | ||
| 2143 | if (ret > 0) | 2161 | if (ret > 0) |
| 2144 | ret = -EINVAL; | 2162 | ret = 0; |
| 2145 | 2163 | ||
| 2146 | return ret; | 2164 | return ret; |
| 2147 | } | 2165 | } |
| @@ -2198,17 +2216,17 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) | |||
| 2198 | static int vgic_its_save_collection_table(struct vgic_its *its) | 2216 | static int vgic_its_save_collection_table(struct vgic_its *its) |
| 2199 | { | 2217 | { |
| 2200 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 2218 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| 2219 | u64 baser = its->baser_coll_table; | ||
| 2220 | gpa_t gpa = BASER_ADDRESS(baser); | ||
| 2201 | struct its_collection *collection; | 2221 | struct its_collection *collection; |
| 2202 | u64 val; | 2222 | u64 val; |
| 2203 | gpa_t gpa; | ||
| 2204 | size_t max_size, filled = 0; | 2223 | size_t max_size, filled = 0; |
| 2205 | int ret, cte_esz = abi->cte_esz; | 2224 | int ret, cte_esz = abi->cte_esz; |
| 2206 | 2225 | ||
| 2207 | gpa = BASER_ADDRESS(its->baser_coll_table); | 2226 | if (!(baser & GITS_BASER_VALID)) |
| 2208 | if (!gpa) | ||
| 2209 | return 0; | 2227 | return 0; |
| 2210 | 2228 | ||
| 2211 | max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; | 2229 | max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; |
| 2212 | 2230 | ||
| 2213 | list_for_each_entry(collection, &its->collection_list, coll_list) { | 2231 | list_for_each_entry(collection, &its->collection_list, coll_list) { |
| 2214 | ret = vgic_its_save_cte(its, collection, gpa, cte_esz); | 2232 | ret = vgic_its_save_cte(its, collection, gpa, cte_esz); |
| @@ -2239,17 +2257,18 @@ static int vgic_its_save_collection_table(struct vgic_its *its) | |||
| 2239 | static int vgic_its_restore_collection_table(struct vgic_its *its) | 2257 | static int vgic_its_restore_collection_table(struct vgic_its *its) |
| 2240 | { | 2258 | { |
| 2241 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); | 2259 | const struct vgic_its_abi *abi = vgic_its_get_abi(its); |
| 2260 | u64 baser = its->baser_coll_table; | ||
| 2242 | int cte_esz = abi->cte_esz; | 2261 | int cte_esz = abi->cte_esz; |
| 2243 | size_t max_size, read = 0; | 2262 | size_t max_size, read = 0; |
| 2244 | gpa_t gpa; | 2263 | gpa_t gpa; |
| 2245 | int ret; | 2264 | int ret; |
| 2246 | 2265 | ||
| 2247 | if (!(its->baser_coll_table & GITS_BASER_VALID)) | 2266 | if (!(baser & GITS_BASER_VALID)) |
| 2248 | return 0; | 2267 | return 0; |
| 2249 | 2268 | ||
| 2250 | gpa = BASER_ADDRESS(its->baser_coll_table); | 2269 | gpa = BASER_ADDRESS(baser); |
| 2251 | 2270 | ||
| 2252 | max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; | 2271 | max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; |
| 2253 | 2272 | ||
| 2254 | while (read < max_size) { | 2273 | while (read < max_size) { |
| 2255 | ret = vgic_its_restore_cte(its, gpa, cte_esz); | 2274 | ret = vgic_its_restore_cte(its, gpa, cte_esz); |
| @@ -2258,6 +2277,10 @@ static int vgic_its_restore_collection_table(struct vgic_its *its) | |||
| 2258 | gpa += cte_esz; | 2277 | gpa += cte_esz; |
| 2259 | read += cte_esz; | 2278 | read += cte_esz; |
| 2260 | } | 2279 | } |
| 2280 | |||
| 2281 | if (ret > 0) | ||
| 2282 | return 0; | ||
| 2283 | |||
| 2261 | return ret; | 2284 | return ret; |
| 2262 | } | 2285 | } |
| 2263 | 2286 | ||
