* Add a single SMMU entry. This function does not sleep. */
| 3692 | * Add a single SMMU entry. This function does not sleep. |
| 3693 | */ |
| 3694 | int |
| 3695 | pmap_senter(pmap_t pmap, vm_offset_t va, vm_paddr_t pa, |
| 3696 | vm_prot_t prot, u_int flags) |
| 3697 | { |
| 3698 | pd_entry_t *pde; |
| 3699 | pt_entry_t new_l3, orig_l3; |
| 3700 | pt_entry_t *l3; |
| 3701 | vm_page_t mpte; |
| 3702 | int lvl; |
| 3703 | int rv; |
| 3704 | |
| 3705 | PMAP_ASSERT_STAGE1(pmap); |
| 3706 | KASSERT(va < VM_MAXUSER_ADDRESS, ("wrong address space")); |
| 3707 | |
| 3708 | va = trunc_page(va); |
| 3709 | new_l3 = (pt_entry_t)(pa | ATTR_DEFAULT | |
| 3710 | ATTR_S1_IDX(VM_MEMATTR_DEVICE) | L3_PAGE); |
| 3711 | if ((prot & VM_PROT_WRITE) == 0) |
| 3712 | new_l3 |= ATTR_S1_AP(ATTR_S1_AP_RO); |
| 3713 | new_l3 |= ATTR_S1_XN; /* Execute never. */ |
| 3714 | new_l3 |= ATTR_S1_AP(ATTR_S1_AP_USER); |
| 3715 | new_l3 |= ATTR_S1_nG; /* Non global. */ |
| 3716 | |
| 3717 | CTR2(KTR_PMAP, "pmap_senter: %.16lx -> %.16lx", va, pa); |
| 3718 | |
| 3719 | PMAP_LOCK(pmap); |
| 3720 | |
| 3721 | /* |
| 3722 | * In the case that a page table page is not |
| 3723 | * resident, we are creating it here. |
| 3724 | */ |
| 3725 | retry: |
| 3726 | pde = pmap_pde(pmap, va, &lvl); |
| 3727 | if (pde != NULL && lvl == 2) { |
| 3728 | l3 = pmap_l2_to_l3(pde, va); |
| 3729 | } else { |
| 3730 | mpte = _pmap_alloc_l3(pmap, pmap_l2_pindex(va), NULL); |
| 3731 | if (mpte == NULL) { |
| 3732 | CTR0(KTR_PMAP, "pmap_enter: mpte == NULL"); |
| 3733 | rv = KERN_RESOURCE_SHORTAGE; |
| 3734 | goto out; |
| 3735 | } |
| 3736 | goto retry; |
| 3737 | } |
| 3738 | |
| 3739 | orig_l3 = pmap_load(l3); |
| 3740 | KASSERT(!pmap_l3_valid(orig_l3), ("l3 is valid")); |
| 3741 | |
| 3742 | /* New mapping */ |
| 3743 | pmap_store(l3, new_l3); |
| 3744 | pmap_resident_count_inc(pmap, 1); |
| 3745 | dsb(ishst); |
| 3746 | |
| 3747 | rv = KERN_SUCCESS; |
| 3748 | out: |
| 3749 | PMAP_UNLOCK(pmap); |
| 3750 | |
| 3751 | return (rv); |
no test coverage detected