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 | ||