mirror of https://gitee.com/openeuler/kernel.git
Compare commits
7 Commits
a798801c59
...
b5a510cea9
Author | SHA1 | Date |
---|---|---|
![]() |
b5a510cea9 | |
![]() |
e804018e39 | |
![]() |
477dce52aa | |
![]() |
7c113a988f | |
![]() |
a1f7a27ec5 | |
![]() |
bb836090e7 | |
![]() |
ca105db208 |
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <linux/bitfield.h>
|
||||
#include <asm/kvm_pgtable.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
|
||||
#define KVM_PGTABLE_MAX_LEVELS 4U
|
||||
|
||||
|
@ -174,6 +175,25 @@ static void kvm_set_table_pte(kvm_pte_t *ptep, kvm_pte_t *childp)
|
|||
smp_store_release(ptep, pte);
|
||||
}
|
||||
|
||||
static bool stage2_pte_cacheable(kvm_pte_t pte)
|
||||
{
|
||||
u64 memattr = pte & KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR;
|
||||
return memattr == PAGE_S2_MEMATTR(NORMAL);
|
||||
}
|
||||
|
||||
static bool stage2_pte_executable(kvm_pte_t pte)
|
||||
{
|
||||
return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
|
||||
}
|
||||
|
||||
static void stage2_flush_dcache(void *addr, u64 size)
|
||||
{
|
||||
if (kvm_ncsnp_support || cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
|
||||
return;
|
||||
|
||||
__flush_dcache_area(addr, size);
|
||||
}
|
||||
|
||||
static kvm_pte_t kvm_init_valid_leaf_pte(u64 pa, kvm_pte_t attr, u32 level)
|
||||
{
|
||||
kvm_pte_t pte = kvm_phys_to_pte(pa);
|
||||
|
@ -348,8 +368,16 @@ static bool hyp_map_walker_try_leaf(u64 addr, u64 end, u32 level,
|
|||
|
||||
/* Tolerate KVM recreating the exact same mapping */
|
||||
new = kvm_init_valid_leaf_pte(phys, data->attr, level);
|
||||
if (old != new && !WARN_ON(kvm_pte_valid(old)))
|
||||
if (old != new && !WARN_ON(kvm_pte_valid(old))) {
|
||||
/* Flush data cache before installation of the new PTE */
|
||||
if (stage2_pte_cacheable(new))
|
||||
stage2_flush_dcache(kvm_pte_follow(new), kvm_granule_size(level));
|
||||
|
||||
if (stage2_pte_executable(new))
|
||||
__invalidate_icache_guest_page(__phys_to_pfn(phys),
|
||||
kvm_granule_size(level));
|
||||
smp_store_release(ptep, new);
|
||||
}
|
||||
|
||||
data->phys += granule;
|
||||
return true;
|
||||
|
@ -496,6 +524,13 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
|
|||
put_page(page);
|
||||
}
|
||||
|
||||
/* Flush data cache before installation of the new PTE */
|
||||
if (stage2_pte_cacheable(new))
|
||||
stage2_flush_dcache(kvm_pte_follow(new), kvm_granule_size(level));
|
||||
|
||||
if (stage2_pte_executable(new))
|
||||
__invalidate_icache_guest_page(__phys_to_pfn(phys), kvm_granule_size(level));
|
||||
|
||||
smp_store_release(ptep, new);
|
||||
get_page(page);
|
||||
data->phys += granule;
|
||||
|
@ -652,20 +687,6 @@ int kvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void stage2_flush_dcache(void *addr, u64 size)
|
||||
{
|
||||
if (kvm_ncsnp_support || cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
|
||||
return;
|
||||
|
||||
__flush_dcache_area(addr, size);
|
||||
}
|
||||
|
||||
static bool stage2_pte_cacheable(kvm_pte_t pte)
|
||||
{
|
||||
u64 memattr = pte & KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR;
|
||||
return memattr == PAGE_S2_MEMATTR(NORMAL);
|
||||
}
|
||||
|
||||
static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
|
||||
enum kvm_pgtable_walk_flags flag,
|
||||
void * const arg)
|
||||
|
@ -744,8 +765,16 @@ static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
|
|||
* but worst-case the access flag update gets lost and will be
|
||||
* set on the next access instead.
|
||||
*/
|
||||
if (data->pte != pte)
|
||||
if (data->pte != pte) {
|
||||
/*
|
||||
* Invalidate instruction cache before updating the guest
|
||||
* stage-2 PTE if we are going to add executable permission.
|
||||
*/
|
||||
if (stage2_pte_executable(pte) && !stage2_pte_executable(*ptep))
|
||||
__invalidate_icache_guest_page(__phys_to_pfn(kvm_pte_to_phys(pte)),
|
||||
kvm_granule_size(level));
|
||||
WRITE_ONCE(*ptep, pte);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -615,11 +615,6 @@ static void clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
|
|||
__clean_dcache_guest_page(pfn, size);
|
||||
}
|
||||
|
||||
static void invalidate_icache_guest_page(kvm_pfn_t pfn, unsigned long size)
|
||||
{
|
||||
__invalidate_icache_guest_page(pfn, size);
|
||||
}
|
||||
|
||||
static void kvm_send_hwpoison_signal(unsigned long address, short lsb)
|
||||
{
|
||||
send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current);
|
||||
|
@ -931,13 +926,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
|||
if (writable)
|
||||
prot |= KVM_PGTABLE_PROT_W;
|
||||
|
||||
if (fault_status != FSC_PERM && !device)
|
||||
clean_dcache_guest_page(pfn, vma_pagesize);
|
||||
|
||||
if (exec_fault) {
|
||||
if (exec_fault)
|
||||
prot |= KVM_PGTABLE_PROT_X;
|
||||
invalidate_icache_guest_page(pfn, vma_pagesize);
|
||||
}
|
||||
|
||||
if (device)
|
||||
prot |= KVM_PGTABLE_PROT_DEVICE;
|
||||
|
@ -1422,8 +1412,20 @@ void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled)
|
|||
* If switching it off, need to clean the caches.
|
||||
* Clean + invalidate does the trick always.
|
||||
*/
|
||||
if (now_enabled != was_enabled)
|
||||
stage2_flush_vm(vcpu->kvm);
|
||||
if (now_enabled != was_enabled) {
|
||||
/*
|
||||
* Due to Phytium CPU's cache consistency support,
|
||||
* just flush dcache on one vcpu not all vcpus in the VM.
|
||||
* This can reduce the number of flush dcaches and
|
||||
* improve the efficiency of SMP multi-core startup,
|
||||
* especially for the large VM with hugepages.
|
||||
*/
|
||||
if (read_cpuid_implementor() == ARM_CPU_IMP_PHYTIUM) {
|
||||
if (vcpu->vcpu_id == 0)
|
||||
stage2_flush_vm(vcpu->kvm);
|
||||
} else
|
||||
stage2_flush_vm(vcpu->kvm);
|
||||
}
|
||||
|
||||
/* Caches are now on, stop trapping VM ops (until a S/W op) */
|
||||
if (now_enabled)
|
||||
|
|
|
@ -609,7 +609,7 @@ static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int on
|
|||
index, pid, onoff);
|
||||
|
||||
/* skip invalid PIDs (0x2000) */
|
||||
if (pid > 0x1fff || index > 32)
|
||||
if (pid > 0x1fff || index >= 32)
|
||||
return 0;
|
||||
|
||||
if (onoff)
|
||||
|
|
|
@ -436,6 +436,8 @@ static void ucsi_ccg_update_set_new_cam_cmd(struct ucsi_ccg *uc,
|
|||
|
||||
port = uc->orig;
|
||||
new_cam = UCSI_SET_NEW_CAM_GET_AM(*cmd);
|
||||
if (new_cam >= ARRAY_SIZE(uc->updated))
|
||||
return;
|
||||
new_port = &uc->updated[new_cam];
|
||||
cam = new_port->linked_idx;
|
||||
enter_new_mode = UCSI_SET_NEW_CAM_ENTER(*cmd);
|
||||
|
|
Loading…
Reference in New Issue