diff options
author | markm <markm@FreeBSD.org> | 2013-09-06 17:42:12 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2013-09-06 17:42:12 +0000 |
commit | 9d67aa8bffecbac35da57b6e638e6ae76f81a4be (patch) | |
tree | 0090524dd3d818125109031a4cf05e46ec2d2355 /sys | |
parent | 2fd409fcd71c91841eee3f09280c21b2031c8450 (diff) | |
parent | d13d69ef17e933f4e8a1be14f0558e25dad171c7 (diff) | |
download | FreeBSD-src-9d67aa8bffecbac35da57b6e638e6ae76f81a4be.zip FreeBSD-src-9d67aa8bffecbac35da57b6e638e6ae76f81a4be.tar.gz |
MFC
Diffstat (limited to 'sys')
217 files changed, 5777 insertions, 3150 deletions
diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 79ec5ed..d002b4d 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -168,7 +168,7 @@ global_invltlb: invltlb_ret_clear_pm_save: movq smp_tlb_pmap,%rdx testq %rdx,%rdx - jz invltlb_ret + jz invltlb_ret_rdx testb $SEL_RPL_MASK,NAKE_INTR_CS(%rsp) jz 1f swapgs @@ -179,16 +179,17 @@ invltlb_ret_clear_pm_save: 2: LK btcl %eax,PM_SAVE(%rdx) SUPERALIGN_TEXT -invltlb_ret: +invltlb_ret_rdx: + popq %rdx +invltlb_ret_rax: movq lapic, %rax movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ LK incl smp_tlb_wait - popq %rdx popq %rax jmp doreti_iret SUPERALIGN_TEXT -IDTVEC(invltlb) +IDTVEC(invltlb_pcid) #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) PUSH_FRAME movl PCPU(CPUID), %eax @@ -206,8 +207,6 @@ IDTVEC(invltlb) pushq %rdx movq %cr3,%rax - cmpl $0,pmap_pcid_enabled - je 2f movq $smp_tlb_invpcid,%rdx cmpl $0,(%rdx) @@ -216,8 +215,7 @@ IDTVEC(invltlb) je global_invltlb /* - * Non-zero smp_tlb_invpcid, only invalidate TLB for entries with - * current PCID. + * Only invalidate TLB for entries with current PCID. */ cmpl $0,invpcid_works je 1f @@ -233,21 +231,36 @@ IDTVEC(invltlb) je 2f movq %rdx,%cr3 /* Invalidate, bit 63 is zero. */ btsq $63,%rax - - /* - * Invalidate the TLB if PCID is not enabled. - * Restore the old address space. - */ 2: movq %rax,%cr3 jmp invltlb_ret_clear_pm_save + SUPERALIGN_TEXT +IDTVEC(invltlb) +#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) + PUSH_FRAME + movl PCPU(CPUID), %eax +#ifdef COUNT_XINVLTLB_HITS + incl xhits_gbl(,%rax,4) +#endif +#ifdef COUNT_IPIS + movq ipi_invltlb_counts(,%rax,8),%rax + incq (%rax) +#endif + POP_FRAME +#endif + + pushq %rax + movq %cr3, %rax /* invalidate the TLB */ + movq %rax, %cr3 + jmp invltlb_ret_rax + /* * Single page TLB shootdown */ .text SUPERALIGN_TEXT -IDTVEC(invlpg) +IDTVEC(invlpg_pcid) #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) PUSH_FRAME movl PCPU(CPUID), %eax @@ -264,8 +277,6 @@ IDTVEC(invlpg) pushq %rax pushq %rdx movq $smp_tlb_invpcid,%rdx - cmpl $0,pmap_pcid_enabled - je 3f cmpl $0,invpcid_works jne 2f @@ -291,7 +302,7 @@ IDTVEC(invlpg) btsq $63,%rcx movq %rcx,%cr3 popq %rcx - jmp invltlb_ret + jmp invltlb_ret_rdx /* * Invalidate the TLB entry using INVPCID_ADDR. @@ -300,7 +311,7 @@ IDTVEC(invlpg) xorl %eax,%eax /* invpcid (%rdx),%rax */ .byte 0x66,0x0f,0x38,0x82,0x02 - jmp invltlb_ret + jmp invltlb_ret_rdx /* * PCID is not supported or kernel pmap. @@ -309,7 +320,27 @@ IDTVEC(invlpg) 3: movq 8(%rdx),%rax invlpg (%rax) - jmp invltlb_ret + jmp invltlb_ret_rdx + + SUPERALIGN_TEXT +IDTVEC(invlpg) +#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) + PUSH_FRAME + movl PCPU(CPUID), %eax +#ifdef COUNT_XINVLTLB_HITS + incl xhits_pg(,%rax,4) +#endif +#ifdef COUNT_IPIS + movq ipi_invlpg_counts(,%rax,8),%rax + incq (%rax) +#endif + POP_FRAME +#endif + + pushq %rax + movq smp_tlb_invpcid+8,%rax + invlpg (%rax) /* invalidate single page */ + jmp invltlb_ret_rax /* * Page range TLB shootdown. @@ -334,15 +365,15 @@ IDTVEC(invlrng) pushq %rdx movq $smp_tlb_invpcid,%rdx cmpl $0,pmap_pcid_enabled - jne invlrng_single_page - cmpl $0,invpcid_works - jne invlrng_invpcid + je invlrng_single_page /* kernel pmap - use invlpg to invalidate global mapping */ cmpl $0,(%rdx) je invlrng_single_page cmpl $-1,(%rdx) je global_invltlb + cmpl $0,invpcid_works + jne invlrng_invpcid pushq %rcx movq %cr3,%rcx @@ -362,37 +393,27 @@ IDTVEC(invlrng) btsq $63,%rcx movq %rcx,%cr3 popq %rcx - jmp invltlb_ret + jmp invltlb_ret_rdx invlrng_invpcid: - testb $SEL_RPL_MASK,NAKE_INTR_CS(%rsp) - jz 1f - swapgs -1: pushq %rcx + subq $16,%rsp movq (%rdx),%rcx - movq %rcx,PCPU(INVPCID_DESCR) + movq %rcx,(%rsp) movq 8(%rdx),%rax - movq %rax,PCPU(INVPCID_DESCR)+8 + movq %rax,8(%rsp) movq smp_tlb_addr2,%rcx - xorl %eax,%eax - movq $PC_INVPCID_DESCR,%rdx - gs - subq 8(%rdx),%rcx + subq %rax,%rcx shrq $PAGE_SHIFT,%rcx -2: - gs +1: // invpcid (%rdx),%rax .byte 0x66,0x0f,0x38,0x82,0x02 - gs - addq $PAGE_SIZE,8(%rdx) + addq $PAGE_SIZE,8(%rsp) dec %rcx - jne 2b + jne 1b + addq $16,%rsp popq %rcx - testb $SEL_RPL_MASK,NAKE_INTR_CS(%rsp) - jz invltlb_ret - swapgs - jmp invltlb_ret + jmp invltlb_ret_rdx invlrng_single_page: movq 8(%rdx),%rdx @@ -401,7 +422,7 @@ invlrng_single_page: addq $PAGE_SIZE,%rdx cmpq %rax,%rdx jb 1b - jmp invltlb_ret + jmp invltlb_ret_rdx /* * Invalidate cache. @@ -418,9 +439,8 @@ IDTVEC(invlcache) #endif pushq %rax - pushq %rdx wbinvd - jmp invltlb_ret + jmp invltlb_ret_rax /* * Handler for IPIs sent via the per-cpu IPI bitmap. diff --git a/sys/amd64/amd64/db_disasm.c b/sys/amd64/amd64/db_disasm.c index 46144e0..b229909 100644 --- a/sys/amd64/amd64/db_disasm.c +++ b/sys/amd64/amd64/db_disasm.c @@ -127,7 +127,7 @@ struct finst { static const struct inst db_inst_0f388x[] = { /*80*/ { "", TRUE, SDEP, op2(E, Rq), "invept" }, /*81*/ { "", TRUE, SDEP, op2(E, Rq), "invvpid" }, -/*82*/ { "", FALSE, NONE, 0, 0 }, +/*82*/ { "", TRUE, SDEP, op2(E, Rq), "invpcid" }, /*83*/ { "", FALSE, NONE, 0, 0 }, /*84*/ { "", FALSE, NONE, 0, 0 }, /*85*/ { "", FALSE, NONE, 0, 0 }, diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index 62017e7..028a2cd 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -228,7 +228,6 @@ ASSYM(PC_LDT, offsetof(struct pcpu, pc_ldt)); ASSYM(PC_COMMONTSSP, offsetof(struct pcpu, pc_commontssp)); ASSYM(PC_TSS, offsetof(struct pcpu, pc_tss)); ASSYM(PC_PM_SAVE_CNT, offsetof(struct pcpu, pc_pm_save_cnt)); -ASSYM(PC_INVPCID_DESCR, offsetof(struct pcpu, pc_invpcid_descr)); ASSYM(LA_VER, offsetof(struct LAPIC, version)); ASSYM(LA_TPR, offsetof(struct LAPIC, tpr)); diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 530aa61..3addd43 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -127,6 +127,8 @@ static u_long *ipi_hardclock_counts[MAXCPU]; extern inthand_t IDTVEC(fast_syscall), IDTVEC(fast_syscall32); +extern int pmap_pcid_enabled; + /* * Local data and functions. */ @@ -524,8 +526,15 @@ cpu_mp_start(void) } /* Install an inter-CPU IPI for TLB invalidation */ - setidt(IPI_INVLTLB, IDTVEC(invltlb), SDT_SYSIGT, SEL_KPL, 0); - setidt(IPI_INVLPG, IDTVEC(invlpg), SDT_SYSIGT, SEL_KPL, 0); + if (pmap_pcid_enabled) { + setidt(IPI_INVLTLB, IDTVEC(invltlb_pcid), SDT_SYSIGT, + SEL_KPL, 0); + setidt(IPI_INVLPG, IDTVEC(invlpg_pcid), SDT_SYSIGT, + SEL_KPL, 0); + } else { + setidt(IPI_INVLTLB, IDTVEC(invltlb), SDT_SYSIGT, SEL_KPL, 0); + setidt(IPI_INVLPG, IDTVEC(invlpg), SDT_SYSIGT, SEL_KPL, 0); + } setidt(IPI_INVLRNG, IDTVEC(invlrng), SDT_SYSIGT, SEL_KPL, 0); /* Install an inter-CPU IPI for cache invalidation. */ @@ -605,8 +614,6 @@ cpu_mp_announce(void) } } -extern int pmap_pcid_enabled; - /* * AP CPU's call this to initialize themselves. */ @@ -1141,8 +1148,7 @@ smp_tlb_shootdown(u_int vector, pmap_t pmap, vm_offset_t addr1, smp_tlb_invpcid.pcid = 0; } else { smp_tlb_invpcid.pcid = pmap->pm_pcid; - pcid_cr3 = DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4) | - (pmap->pm_pcid == -1 ? 0 : pmap->pm_pcid); + pcid_cr3 = pmap->pm_cr3; } smp_tlb_addr2 = addr2; smp_tlb_pmap = pmap; @@ -1176,8 +1182,7 @@ smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, pmap_t pmap, smp_tlb_invpcid.pcid = 0; } else { smp_tlb_invpcid.pcid = pmap->pm_pcid; - pcid_cr3 = DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4) | - (pmap->pm_pcid == -1 ? 0 : pmap->pm_pcid); + pcid_cr3 = pmap->pm_cr3; } smp_tlb_addr2 = addr2; smp_tlb_pmap = pmap; diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index d905961..8940d4a 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -315,7 +315,6 @@ static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa, static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va); -static int pmap_pvh_wired_mappings(struct md_page *pvh, int count); static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode); static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); @@ -329,8 +328,6 @@ static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp); static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); -static boolean_t pmap_is_modified_pvh(struct md_page *pvh); -static boolean_t pmap_is_referenced_pvh(struct md_page *pvh); static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); static void pmap_pde_attr(pd_entry_t *pde, int cache_bits); @@ -728,6 +725,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) */ PMAP_LOCK_INIT(kernel_pmap); kernel_pmap->pm_pml4 = (pdp_entry_t *)PHYS_TO_DMAP(KPML4phys); + kernel_pmap->pm_cr3 = KPML4phys; CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */ CPU_ZERO(&kernel_pmap->pm_save); TAILQ_INIT(&kernel_pmap->pm_pvchunk); @@ -1049,8 +1047,7 @@ pmap_invalidate_page_pcid(pmap_t pmap, vm_offset_t va) cr3 = rcr3(); critical_enter(); - load_cr3(DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4) | pmap->pm_pcid | - CR3_PCID_SAVE); + load_cr3(pmap->pm_cr3 | CR3_PCID_SAVE); invlpg(va); load_cr3(cr3 | CR3_PCID_SAVE); critical_exit(); @@ -1137,8 +1134,7 @@ pmap_invalidate_range_pcid(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) cr3 = rcr3(); critical_enter(); - load_cr3(DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4) | pmap->pm_pcid | - CR3_PCID_SAVE); + load_cr3(pmap->pm_cr3 | CR3_PCID_SAVE); for (addr = sva; addr < eva; addr += PAGE_SIZE) invlpg(addr); load_cr3(cr3 | CR3_PCID_SAVE); @@ -1239,8 +1235,7 @@ pmap_invalidate_all(pmap_t pmap) * Bit 63 is clear, pcid TLB * entries are invalidated. */ - load_cr3(DMAP_TO_PHYS((vm_offset_t) - pmap->pm_pml4) | pmap->pm_pcid); + load_cr3(pmap->pm_cr3); load_cr3(cr3 | CR3_PCID_SAVE); critical_exit(); } @@ -1862,6 +1857,7 @@ pmap_pinit0(pmap_t pmap) PMAP_LOCK_INIT(pmap); pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys); + pmap->pm_cr3 = KPML4phys; pmap->pm_root.rt_root = 0; CPU_ZERO(&pmap->pm_active); CPU_ZERO(&pmap->pm_save); @@ -1869,7 +1865,6 @@ pmap_pinit0(pmap_t pmap) TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); pmap->pm_pcid = pmap_pcid_enabled ? 0 : -1; - CPU_ZERO(&pmap->pm_save); } /* @@ -1889,7 +1884,8 @@ pmap_pinit(pmap_t pmap) VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) VM_WAIT; - pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pml4pg)); + pmap->pm_cr3 = VM_PAGE_TO_PHYS(pml4pg); + pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(pmap->pm_cr3); if ((pml4pg->flags & PG_ZERO) == 0) pagezero(pmap->pm_pml4); @@ -1911,7 +1907,13 @@ pmap_pinit(pmap_t pmap) CPU_ZERO(&pmap->pm_active); TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); - pmap->pm_pcid = pmap_pcid_enabled ? alloc_unr(&pcid_unr) : -1; + if (pmap_pcid_enabled) { + pmap->pm_pcid = alloc_unr(&pcid_unr); + if (pmap->pm_pcid != -1) + pmap->pm_cr3 |= pmap->pm_pcid; + } else { + pmap->pm_pcid = -1; + } CPU_ZERO(&pmap->pm_save); return (1); @@ -4599,42 +4601,61 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m) int pmap_page_wired_mappings(vm_page_t m) { - int count; - - count = 0; - if ((m->oflags & VPO_UNMANAGED) != 0) - return (count); - rw_wlock(&pvh_global_lock); - count = pmap_pvh_wired_mappings(&m->md, count); - if ((m->flags & PG_FICTITIOUS) == 0) { - count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)), - count); - } - rw_wunlock(&pvh_global_lock); - return (count); -} - -/* - * pmap_pvh_wired_mappings: - * - * Return the updated number "count" of managed mappings that are wired. - */ -static int -pmap_pvh_wired_mappings(struct md_page *pvh, int count) -{ + struct rwlock *lock; + struct md_page *pvh; pmap_t pmap; pt_entry_t *pte; pv_entry_t pv; + int count, md_gen, pvh_gen; - rw_assert(&pvh_global_lock, RA_WLOCKED); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + if ((m->oflags & VPO_UNMANAGED) != 0) + return (0); + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); + rw_rlock(lock); +restart: + count = 0; + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } pte = pmap_pte(pmap, pv->pv_va); if ((*pte & PG_W) != 0) count++; PMAP_UNLOCK(pmap); } + if ((m->flags & PG_FICTITIOUS) == 0) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + pvh_gen = pvh->pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen || + pvh_gen != pvh->pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } + pte = pmap_pde(pmap, pv->pv_va); + if ((*pte & PG_W) != 0) + count++; + PMAP_UNLOCK(pmap); + } + } + rw_runlock(lock); + rw_runlock(&pvh_global_lock); return (count); } @@ -4830,6 +4851,69 @@ pmap_remove_pages(pmap_t pmap) pmap_free_zero_pages(&free); } +static boolean_t +pmap_page_test_mappings(vm_page_t m, pt_entry_t mask) +{ + struct rwlock *lock; + pv_entry_t pv; + struct md_page *pvh; + pt_entry_t *pte; + pmap_t pmap; + int md_gen, pvh_gen; + boolean_t rv; + + rv = FALSE; + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); + rw_rlock(lock); +restart: + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } + pte = pmap_pte(pmap, pv->pv_va); + rv = (*pte & mask) == mask; + PMAP_UNLOCK(pmap); + if (rv) + goto out; + } + if ((m->flags & PG_FICTITIOUS) == 0) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + pvh_gen = pvh->pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen || + pvh_gen != pvh->pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } + pte = pmap_pde(pmap, pv->pv_va); + rv = (*pte & mask) == mask; + PMAP_UNLOCK(pmap); + if (rv) + goto out; + } + } +out: + rw_runlock(lock); + rw_runlock(&pvh_global_lock); + return (rv); +} + /* * pmap_is_modified: * @@ -4839,7 +4923,6 @@ pmap_remove_pages(pmap_t pmap) boolean_t pmap_is_modified(vm_page_t m) { - boolean_t rv; KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("pmap_is_modified: page %p is not managed", m)); @@ -4852,39 +4935,7 @@ pmap_is_modified(vm_page_t m) VM_OBJECT_ASSERT_WLOCKED(m->object); if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0) return (FALSE); - rw_wlock(&pvh_global_lock); - rv = pmap_is_modified_pvh(&m->md) || - ((m->flags & PG_FICTITIOUS) == 0 && - pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m)))); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * Returns TRUE if any of the given mappings were used to modify - * physical memory. Otherwise, returns FALSE. Both page and 2mpage - * mappings are supported. - */ -static boolean_t -pmap_is_modified_pvh(struct md_page *pvh) -{ - pv_entry_t pv; - pt_entry_t *pte; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte = pmap_pte(pmap, pv->pv_va); - rv = (*pte & (PG_M | PG_RW)) == (PG_M | PG_RW); - PMAP_UNLOCK(pmap); - if (rv) - break; - } - return (rv); + return (pmap_page_test_mappings(m, PG_M | PG_RW)); } /* @@ -4920,42 +4971,10 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr) boolean_t pmap_is_referenced(vm_page_t m) { - boolean_t rv; KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("pmap_is_referenced: page %p is not managed", m)); - rw_wlock(&pvh_global_lock); - rv = pmap_is_referenced_pvh(&m->md) || - ((m->flags & PG_FICTITIOUS) == 0 && - pmap_is_referenced_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m)))); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * Returns TRUE if any of the given mappings were referenced and FALSE - * otherwise. Both page and 2mpage mappings are supported. - */ -static boolean_t -pmap_is_referenced_pvh(struct md_page *pvh) -{ - pv_entry_t pv; - pt_entry_t *pte; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte = pmap_pte(pmap, pv->pv_va); - rv = (*pte & (PG_A | PG_V)) == (PG_A | PG_V); - PMAP_UNLOCK(pmap); - if (rv) - break; - } - return (rv); + return (pmap_page_test_mappings(m, PG_A | PG_V)); } /* @@ -5081,8 +5100,8 @@ pmap_ts_referenced(vm_page_t m) lock = VM_PAGE_TO_PV_LIST_LOCK(m); pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); rtval = 0; -retry: rw_wlock(lock); +retry: if ((m->flags & PG_FICTITIOUS) != 0) goto small_mappings; TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, pvn) { @@ -5094,7 +5113,6 @@ retry: rw_wlock(lock); if (pvh_gen != pvh->pv_gen) { PMAP_UNLOCK(pmap); - rw_wunlock(lock); goto retry; } } @@ -5149,7 +5167,6 @@ small_mappings: if (pvh_gen != pvh->pv_gen || md_gen != m->md.pv_gen) { PMAP_UNLOCK(pmap); - rw_wunlock(lock); goto retry; } } @@ -5936,7 +5953,6 @@ pmap_activate(struct thread *td) { pmap_t pmap, oldpmap; u_int cpuid; - u_int64_t cr3; critical_enter(); pmap = vmspace_pmap(td->td_proc->p_vmspace); @@ -5951,11 +5967,8 @@ pmap_activate(struct thread *td) CPU_SET(cpuid, &pmap->pm_active); CPU_SET(cpuid, &pmap->pm_save); #endif - cr3 = DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4); - if (pmap->pm_pcid != -1) - cr3 |= pmap->pm_pcid; - td->td_pcb->pcb_cr3 = cr3; - load_cr3(cr3); + td->td_pcb->pcb_cr3 = pmap->pm_cr3; + load_cr3(pmap->pm_cr3); PCPU_SET(curpmap, pmap); critical_exit(); } diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index 3764f72..7253fe2 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/pioctl.h> #include <sys/proc.h> -#include <sys/sf_buf.h> #include <sys/smp.h> #include <sys/sysctl.h> #include <sys/sysent.h> @@ -220,9 +219,7 @@ cpu_fork(td1, p2, td2, flags) * return address on stack. These are the kernel mode register values. */ pmap2 = vmspace_pmap(p2->p_vmspace); - pcb2->pcb_cr3 = DMAP_TO_PHYS((vm_offset_t)pmap2->pm_pml4); - if (pmap2->pm_pcid != -1) - pcb2->pcb_cr3 |= pmap2->pm_pcid; + pcb2->pcb_cr3 = pmap2->pm_cr3; pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */ pcb2->pcb_rbp = 0; pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *); @@ -697,27 +694,6 @@ cpu_reset_real() } /* - * Allocate an sf_buf for the given vm_page. On this machine, however, there - * is no sf_buf object. Instead, an opaque pointer to the given vm_page is - * returned. - */ -struct sf_buf * -sf_buf_alloc(struct vm_page *m, int pri) -{ - - return ((struct sf_buf *)m); -} - -/* - * Free the sf_buf. In fact, do nothing because there are no resources - * associated with the sf_buf. - */ -void -sf_buf_free(struct sf_buf *sf) -{ -} - -/* * Software interrupt handler for queued VM system processing. */ void diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h index 0e11975..387df1a 100644 --- a/sys/amd64/include/pcpu.h +++ b/sys/amd64/include/pcpu.h @@ -68,7 +68,6 @@ /* Pointer to the CPU TSS descriptor */ \ struct system_segment_descriptor *pc_tss; \ uint64_t pc_pm_save_cnt; \ - char pc_invpcid_descr[16]; \ u_int pc_cmci_mask; /* MCx banks for CMCI */ \ uint64_t pc_dbreg[16]; /* ddb debugging regs */ \ int pc_dbreg_cmd; /* ddb debugging reg cmd */ \ diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index fa42389..b570cb7 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -238,6 +238,7 @@ struct md_page { struct pmap { struct mtx pm_mtx; pml4_entry_t *pm_pml4; /* KVA of level 4 page table */ + uint64_t pm_cr3; TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ cpuset_t pm_active; /* active on cpus */ cpuset_t pm_save; /* Context valid on cpus mask */ diff --git a/sys/amd64/include/sf_buf.h b/sys/amd64/include/sf_buf.h index b5245e6..729e8e5 100644 --- a/sys/amd64/include/sf_buf.h +++ b/sys/amd64/include/sf_buf.h @@ -41,6 +41,18 @@ */ struct sf_buf; +static inline struct sf_buf * +sf_buf_alloc(struct vm_page *m, int pri) +{ + + return ((struct sf_buf *)m); +} + +static inline void +sf_buf_free(struct sf_buf *sf) +{ +} + static __inline vm_offset_t sf_buf_kva(struct sf_buf *sf) { diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index d6cd476..d1b366b 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -45,7 +45,9 @@ extern u_long *ipi_rendezvous_counts[MAXCPU]; /* IPI handlers */ inthand_t + IDTVEC(invltlb_pcid), /* TLB shootdowns - global, pcid enabled */ IDTVEC(invltlb), /* TLB shootdowns - global */ + IDTVEC(invlpg_pcid), /* TLB shootdowns - 1 page, pcid enabled */ IDTVEC(invlpg), /* TLB shootdowns - 1 page */ IDTVEC(invlrng), /* TLB shootdowns - page range */ IDTVEC(invlcache), /* Write back and invalidate cache */ diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index 65f034a..3dd8f7a 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -519,6 +519,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, } */ bsd_args; int error; struct file *fp; + cap_rights_t rights; error = 0; bsd_args.flags = 0; @@ -567,7 +568,9 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, * protection options specified. */ - if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) + error = fget(td, bsd_args.fd, + cap_rights_init(&rights, CAP_MMAP), &fp); + if (error != 0) return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); diff --git a/sys/amd64/vmm/vmm_msr.c b/sys/amd64/vmm/vmm_msr.c index d97c819..0ccd7af 100644 --- a/sys/amd64/vmm/vmm_msr.c +++ b/sys/amd64/vmm/vmm_msr.c @@ -57,6 +57,7 @@ static struct vmm_msr vmm_msr[] = { { MSR_PAT, VMM_MSR_F_EMULATE | VMM_MSR_F_INVALID }, { MSR_BIOS_SIGN,VMM_MSR_F_EMULATE }, { MSR_MCG_CAP, VMM_MSR_F_EMULATE | VMM_MSR_F_READONLY }, + { MSR_IA32_MISC_ENABLE, VMM_MSR_F_EMULATE | VMM_MSR_F_READONLY }, }; #define vmm_msr_num (sizeof(vmm_msr) / sizeof(vmm_msr[0])) @@ -91,7 +92,7 @@ void guest_msrs_init(struct vm *vm, int cpu) { int i; - uint64_t *guest_msrs; + uint64_t *guest_msrs, misc; guest_msrs = vm_guest_msrs(vm, cpu); @@ -115,6 +116,20 @@ guest_msrs_init(struct vm *vm, int cpu) PAT_VALUE(6, PAT_UNCACHED) | PAT_VALUE(7, PAT_UNCACHEABLE); break; + case MSR_IA32_MISC_ENABLE: + misc = rdmsr(MSR_IA32_MISC_ENABLE); + /* + * Set mandatory bits + * 11: branch trace disabled + * 12: PEBS unavailable + * Clear unsupported features + * 16: SpeedStep enable + * 18: enable MONITOR FSM + */ + misc |= (1 << 12) | (1 << 11); + misc &= ~((1 << 18) | (1 << 16)); + guest_msrs[i] = misc; + break; default: panic("guest_msrs_init: missing initialization for msr " "0x%0x", vmm_msr[i].num); diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 262efbd..4416c53 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -200,6 +200,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, case CPUID_0000_0006: case CPUID_0000_0007: case CPUID_0000_000A: + case CPUID_0000_000D: /* * Handle the access, but report 0 for * all options diff --git a/sys/amd64/vmm/x86.h b/sys/amd64/vmm/x86.h index 368e967..8401c15 100644 --- a/sys/amd64/vmm/x86.h +++ b/sys/amd64/vmm/x86.h @@ -38,6 +38,7 @@ #define CPUID_0000_0007 (0x7) #define CPUID_0000_000A (0xA) #define CPUID_0000_000B (0xB) +#define CPUID_0000_000D (0xD) #define CPUID_8000_0000 (0x80000000) #define CPUID_8000_0001 (0x80000001) #define CPUID_8000_0002 (0x80000002) diff --git a/sys/arm/conf/DIGI-CCWMX53 b/sys/arm/conf/DIGI-CCWMX53 new file mode 100644 index 0000000..5aec9fe --- /dev/null +++ b/sys/arm/conf/DIGI-CCWMX53 @@ -0,0 +1,175 @@ +# Kernel configuration for Digi ConnectCore Wi-i.MX53 boards +# +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +ident DIGI-CCWMX53 + +include "../freescale/imx/std.imx53" + +makeoptions WITHOUT_MODULES="ahc" + +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +#options DEBUG + +options SCHED_4BSD # 4BSD scheduler +#options PREEMPTION # Enable kernel thread preemption +options INET # InterNETworking +options INET6 # IPv6 communications protocols +#options SCTP # Stream Control Transmission Protocol +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +#options MD_ROOT # MD is a potential root device +options NFSCL # New Network Filesystem Client +#options NFSD # New Network Filesystem Server +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +#options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # TMP Memory Filesystem +options GEOM_PART_GPT # GUID Partition Tables. +options GEOM_LABEL # Provides labelization +#options COMPAT_FREEBSD5 # Compatible with FreeBSD5 +#options COMPAT_FREEBSD6 # Compatible with FreeBSD6 +#options COMPAT_FREEBSD7 # Compatible with FreeBSD7 +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options INCLUDE_CONFIG_FILE # Include this file in kernel +options VFP # vfp/neon + +# required for netbooting +#options BOOTP +#options BOOTP_COMPAT +#options BOOTP_NFSROOT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 + +#options ROOTDEVNAME=\"ufs:ada0s2a\" + + +# kernel/memory size reduction +#options MUTEX_NOINLINE +#options NO_FFS_SNAPSHOT +#options NO_SWAPPING +#options NO_SYSCTL_DESCR +#options RWLOCK_NOINLINE + +# Debugging support. Always need this: +options KDB # Enable kernel debugger support. +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic. +# For full debugger support use this instead: +options DDB # Support DDB. +#options GDB # Support remote GDB. +options DEADLKRES # Enable the deadlock resolver +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +options WITNESS # Enable checks to detect deadlocks and cycles + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf # Berkeley packet filter + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +#device vlan # 802.1Q VLAN support +#device tun # Packet tunnel. +#device md # Memory "disks" +#device gif # IPv6 and IPv4 tunneling +#device faith # IPv6-to-IPv4 relaying (translation) +#device firmware # firmware assist module + +# Serial (COM) ports +#device uart # Multi-uart driver +options ALT_BREAK_TO_DEBUGGER + +device ata +device atapci # Only for helper functions +device imxata +options ATA_STATIC_ID # Static device numbering + +device iomux # IO Multiplexor + +device gpio +device gpioled + +device fsliic +device iic +device iicbus + +# SCSI peripherals +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device cd # CD +device pass # Passthrough device (direct SCSI access) + +# USB support +#options USB_DEBUG # enable debug msgs +#device ehci # OHCI USB interface +#device usb # USB Bus (required) +#device umass # Disks/Mass storage - Requires scbus and da +#device uhid # "Human Interface Devices" +#device ukbd # Allow keyboard like HIDs to control console +#device ums + +# USB Ethernet, requires miibus +#device miibus +#device aue # ADMtek USB Ethernet +#device axe # ASIX Electronics USB Ethernet +#device cdce # Generic USB over Ethernet +#device cue # CATC USB Ethernet +#device kue # Kawasaki LSI USB Ethernet +#device rue # RealTek RTL8150 USB Ethernet +#device udav # Davicom DM9601E USB + +# USB Wireless +#device rum # Ralink Technology RT2501USB wireless NICs + +# Watchdog timer. +# WARNING: can't be disabled!!! +device imxwdt # Watchdog + +# Wireless NIC cards +device wlan # 802.11 support +device wlan_wep # 802.11 WEP support +device wlan_ccmp # 802.11 CCMP support +device wlan_tkip # 802.11 TKIP support +device wlan_amrr # AMRR transmit rate control algorithm + +# Flattened Device Tree +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=digi-ccwmx53.dts + +# NOTE: serial console will be disabled if syscons enabled +# Uncomment following lines for framebuffer/syscons support +#device sc +#device kbdmux +#options SC_DFLT_FONT # compile font in +#makeoptions SC_DFLT_FONT=cp437 diff --git a/sys/arm/freescale/imx/files.imx53 b/sys/arm/freescale/imx/files.imx53 new file mode 100644 index 0000000..5d709ed --- /dev/null +++ b/sys/arm/freescale/imx/files.imx53 @@ -0,0 +1,51 @@ +# $FreeBSD$ +arm/arm/bus_space_asm_generic.S standard +arm/arm/bus_space_generic.c standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard +kern/kern_clocksource.c standard + +# Init +arm/freescale/imx/imx53_machdep.c standard +arm/freescale/imx/common.c standard +arm/freescale/imx/bus_space.c standard + +# Dummy serial console +arm/freescale/imx/console.c standard + +# TrustZone Interrupt Controller +arm/freescale/imx/tzic.c standard + +# IOMUX - external pins multiplexor +arm/freescale/imx/imx51_iomux.c optional iomux + +# GPIO +arm/freescale/imx/imx51_gpio.c optional gpio + +# Generic Periodic Timer +arm/freescale/imx/imx_gpt.c standard + +# Clock Configuration Manager +arm/freescale/imx/imx51_ccm.c standard + +# i.MX5xx PATA controller +dev/ata/chipsets/ata-fsl.c optional imxata + +# UART driver +#dev/uart/uart_dev_imx.c optional uart + +# USB join controller (1 OTG, 3 EHCI) +dev/usb/controller/ehci_imx.c optional ehci + +# Watchdog +arm/freescale/imx/imx_wdog.c optional imxwdt + +# i2c +arm/freescale/imx/i2c.c optional fsliic +dev/ofw/ofw_iicbus.c optional fsliic + +# IPU - Image Processing Unit (frame buffer also) +arm/freescale/imx/imx51_ipuv3.c optional sc + diff --git a/sys/arm/freescale/imx/imx51_ccm.c b/sys/arm/freescale/imx/imx51_ccm.c index 529dd74..e8b4699 100644 --- a/sys/arm/freescale/imx/imx51_ccm.c +++ b/sys/arm/freescale/imx/imx51_ccm.c @@ -140,7 +140,8 @@ static int imxccm_match(device_t dev) { - if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm")) + if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") && + !ofw_bus_is_compatible(dev, "fsl,imx53-ccm")) return (ENXIO); device_set_desc(dev, "Freescale Clock Control Module"); diff --git a/sys/arm/freescale/imx/imx51_gpio.c b/sys/arm/freescale/imx/imx51_gpio.c index ecccf8e..f9890a8 100644 --- a/sys/arm/freescale/imx/imx51_gpio.c +++ b/sys/arm/freescale/imx/imx51_gpio.c @@ -370,7 +370,8 @@ static int imx51_gpio_probe(device_t dev) { - if (ofw_bus_is_compatible(dev, "fsl,imx51-gpio")) { + if (ofw_bus_is_compatible(dev, "fsl,imx51-gpio") || + ofw_bus_is_compatible(dev, "fsl,imx53-gpio")) { device_set_desc(dev, "i.MX515 GPIO Controller"); return (BUS_PROBE_DEFAULT); } diff --git a/sys/arm/freescale/imx/imx51_iomux.c b/sys/arm/freescale/imx/imx51_iomux.c index a37776e..5096f2c 100644 --- a/sys/arm/freescale/imx/imx51_iomux.c +++ b/sys/arm/freescale/imx/imx51_iomux.c @@ -106,7 +106,8 @@ static int iomux_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "fsl,imx51-iomux")) + if (!ofw_bus_is_compatible(dev, "fsl,imx51-iomux") && + !ofw_bus_is_compatible(dev, "fsl,imx53-iomux")) return (ENXIO); device_set_desc(dev, "Freescale i.MX51 IO pins multiplexor"); diff --git a/sys/arm/freescale/imx/imx53_machdep.c b/sys/arm/freescale/imx/imx53_machdep.c new file mode 100644 index 0000000..0c0a1a6 --- /dev/null +++ b/sys/arm/freescale/imx/imx53_machdep.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * Copyright (c) 2012, 2013 The FreeBSD Foundation + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_platform.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/reboot.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/bus.h> +#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */ +#include <machine/machdep.h> +#include <machine/pmap.h> + +#include <dev/fdt/fdt_common.h> + +#define IMX53_DEV_VIRT_BASE 0xe0000000 + +vm_offset_t +initarm_lastaddr(void) +{ + + boothowto |= RB_VERBOSE|RB_MULTIPLE; + bootverbose = 1; + + if (fdt_immr_addr(IMX53_DEV_VIRT_BASE) != 0) + while (1); + + /* Platform-specific initialisation */ + return (fdt_immr_va - ARM_NOCACHE_KVA_SIZE); +} + +/* + * Set initial values of GPIO output ports + */ +void +initarm_gpio_init(void) +{ + +} + +void +initarm_late_init(void) +{ + +} + +#define FDT_DEVMAP_MAX 2 +static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = { + { 0, 0, 0, 0, 0, }, + { 0, 0, 0, 0, 0, } +}; + +/* + * Construct pmap_devmap[] with DT-derived config data. + */ +int +platform_devmap_init(void) +{ + + /* + * Map segment where UART1 and UART2 located. + */ + fdt_devmap[0].pd_va = IMX53_DEV_VIRT_BASE + 0x03f00000; + fdt_devmap[0].pd_pa = 0x53f00000; + fdt_devmap[0].pd_size = 0x00100000; + fdt_devmap[0].pd_prot = VM_PROT_READ | VM_PROT_WRITE; + fdt_devmap[0].pd_cache = PTE_NOCACHE; + + pmap_devmap_bootstrap_table = &fdt_devmap[0]; + + return (0); +} + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + return (NULL); +} + +int +bus_dma_get_range_nb(void) +{ + + return (0); +} + +void +cpu_reset(void) +{ + + printf("Reset ...\n"); + /* Clear n_reset flag */ + *((volatile u_int16_t *)(IMX53_DEV_VIRT_BASE + 0x03f98000)) = + (u_int16_t)0; + while (1); +} diff --git a/sys/arm/freescale/imx/imx_gpt.c b/sys/arm/freescale/imx/imx_gpt.c index e37ea6b..de726d0 100644 --- a/sys/arm/freescale/imx/imx_gpt.c +++ b/sys/arm/freescale/imx/imx_gpt.c @@ -112,7 +112,8 @@ static int imx_gpt_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "fsl,imx51-gpt")) + if (!ofw_bus_is_compatible(dev, "fsl,imx51-gpt") && + !ofw_bus_is_compatible(dev, "fsl,imx53-gpt")) return (ENXIO); device_set_desc(dev, "Freescale i.MX GPT timer"); diff --git a/sys/arm/freescale/imx/imx_wdog.c b/sys/arm/freescale/imx/imx_wdog.c index 86fc256..02c454e 100644 --- a/sys/arm/freescale/imx/imx_wdog.c +++ b/sys/arm/freescale/imx/imx_wdog.c @@ -130,7 +130,8 @@ static int imx_wdog_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "fsl,imx51-wdt")) + if (!ofw_bus_is_compatible(dev, "fsl,imx51-wdt") && + !ofw_bus_is_compatible(dev, "fsl,imx53-wdt")) return (ENXIO); device_set_desc(dev, "Freescale i.MX5xx Watchdog Timer"); diff --git a/sys/arm/freescale/imx/std.imx53 b/sys/arm/freescale/imx/std.imx53 new file mode 100644 index 0000000..a7bdba2 --- /dev/null +++ b/sys/arm/freescale/imx/std.imx53 @@ -0,0 +1,15 @@ +# $FreeBSD$ +machine arm armv6 +cpu CPU_CORTEXA +makeoptions ARM_LITTLE_ENDIAN +options ARM_L2_PIPT + +options KERNVIRTADDR=0xc0100000 +makeoptions KERNVIRTADDR=0xc0100000 +options KERNPHYSADDR=0x70100000 +makeoptions KERNPHYSADDR=0x70100000 +options PHYSADDR=0x70000000 +options STARTUP_PAGETABLE_ADDR=0x71000000 + +files "../freescale/imx/files.imx53" + diff --git a/sys/boot/fdt/dts/digi-ccwmx53.dts b/sys/boot/fdt/dts/digi-ccwmx53.dts new file mode 100644 index 0000000..e71262a --- /dev/null +++ b/sys/boot/fdt/dts/digi-ccwmx53.dts @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2013 Rui Paulo + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Digi ConnectCore Wi-i.MX53 + * + * $FreeBSD$ + */ + +/dts-v1/; +/include/ "imx53x.dtsi" + +/ { + model = "Digi ConnectCore Wi-i.MX53"; + compatible = "digi,imx53-ccwm53"; + + memory { + /* RAM 512M */ + reg = <0x70000000 0x20000000>; + }; + + localbus@18000000 { + ipu3@18000000 { + status = "okay"; + }; + }; + + soc@50000000 { + aips@50000000 { + spba@50000000 { + esdhc@50004000 { + clock-frequency = <216000000>; + status = "okay"; + }; + esdhc@50008000 { + clock-frequency = <216000000>; + status = "okay"; + }; + SSI2: ssi@50014000 { + status = "okay"; + }; + }; + timer@53fa0000 { + status = "okay"; + }; + + /* UART1, console */ + UART1: serial@53fbc000 { + status = "okay"; + clock-frequency = <3000000>; /* XXX */ + }; + + clock@53fd4000 { + status = "okay"; + }; + gpio@53f84000 { + status = "okay"; + }; + gpio@53f88000 { + status = "okay"; + }; + gpio@53f8c000 { + status = "okay"; + }; + gpio@53f90000 { + status = "okay"; + }; + wdog@53f98000 { + status = "okay"; + }; + }; + aips@60000000 { + i2c@63fc4000 { + status = "okay"; + }; + i2c@63fc8000 { + status = "okay"; + }; + audmux@63fd4000 { + status = "okay"; + }; + ide@63fe0000 { + status = "okay"; + }; + }; + }; + + aliases { + UART1 = &UART1; + SSI2 = &SSI2; + }; + + chosen { + bootargs = "-v"; + stdin = "UART1"; + stdout = "UART1"; + }; +}; diff --git a/sys/boot/fdt/dts/imx53x.dtsi b/sys/boot/fdt/dts/imx53x.dtsi new file mode 100644 index 0000000..f8675ee --- /dev/null +++ b/sys/boot/fdt/dts/imx53x.dtsi @@ -0,0 +1,680 @@ +/* + * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2013 Rui Paulo + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Freescale i.MX535 Device Tree Source. + * + * $FreeBSD$ + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + soc = &SOC; + }; + + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "ARM,MCIMX535"; + reg = <0x0>; + d-cache-line-size = <32>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + i-cache-size = <0x8000>; + l2-cache-line-size = <32>; + l2-cache-line = <0x40000>; + timebase-frequency = <0>; + bus-frequency = <0>; + clock-frequency = <0>; + }; + }; + + localbus@0fffc000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + /* This reflects CPU decode windows setup. */ + ranges; + + tzic: tz-interrupt-controller@0fffc000 { + compatible = "fsl,imx53-tzic", "fsl,tzic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x0fffc000 0x00004000>; + }; + /* + * 40000000 40000FFF 4K Debug ROM + * 40001000 40001FFF 4K ETB + * 40002000 40002FFF 4K ETM + * 40003000 40003FFF 4K TPIU + * 40004000 40004FFF 4K CTI0 + * 40005000 40005FFF 4K CTI1 + * 40006000 40006FFF 4K CTI2 + * 40007000 40007FFF 4K CTI3 + * 40008000 40008FFF 4K ARM Debug Unit + * + * 0FFFC000 0FFFCFFF 0x4000 TZIC + */ + }; + + SOC: soc@50000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges = <0x50000000 0x14000000>; + + aips@50000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* Required by many devices, so better to stay first */ + /* 53FD4000 0x4000 CCM */ + clock@53fd4000 { + compatible = "fsl,imx53-ccm"; + /* 63F80000 0x4000 DPLLIP1 */ + /* 63F84000 0x4000 DPLLIP2 */ + /* 63F88000 0x4000 DPLLIP3 */ + reg = <0x53fd4000 0x4000 + 0x63F80000 0x4000 + 0x63F84000 0x4000 + 0x63F88000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <71 72>; + status = "disabled"; + }; + + /* + * GPIO modules moved up - to have it attached for + * drivers which rely on GPIO + */ + /* 53F84000 0x4000 GPIO1 */ + gpio1: gpio@53f84000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53f84000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <50 51 42 43 44 45 46 47 48 49>; + /* TODO: use <> also */ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53F88000 0x4000 GPIO2 */ + gpio2: gpio@53f88000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53f88000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <52 53>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53F8C000 0x4000 GPIO3 */ + gpio3: gpio@53f8c000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53f8c000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <54 55>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53F90000 0x4000 GPIO4 */ + gpio4: gpio@53f90000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53f90000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <56 57>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53FDC000 0x4000 GPIO5 */ + gpio5: gpio@53fdc000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53fdc000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <103 104>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53FE0000 0x4000 GPIO6 */ + gpio6: gpio@53fe0000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53fe0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <105 106>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 53FE4000 0x4000 GPIO5 */ + gpio7: gpio@53fe4000 { + compatible = "fsl,imx53-gpio"; + reg = <0x53fe4000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <107 108>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + spba@50000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* 50004000 0x4000 ESDHC 1 */ + esdhc@50004000 { + compatible = "fsl,imx53-esdhc"; + reg = <0x50004000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <1>; + status = "disabled"; + }; + + /* 50008000 0x4000 ESDHC 2 */ + esdhc@50008000 { + compatible = "fsl,imx53-esdhc"; + reg = <0x50008000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <2>; + status = "disabled"; + }; + + /* 5000C000 0x4000 UART 3 */ + uart3: serial@5000c000 { + compatible = "fsl,imx53-uart", "fsl,imx-uart"; + reg = <0x5000c000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <33>; + status = "disabled"; + }; + + /* 50010000 0x4000 eCSPI1 */ + ecspi@50010000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-ecspi"; + reg = <0x50010000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <36>; + status = "disabled"; + }; + + /* 50014000 0x4000 SSI2 irq30 */ + SSI2: ssi@50014000 { + compatible = "fsl,imx53-ssi"; + reg = <0x50014000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <30>; + status = "disabled"; + }; + + /* 50020000 0x4000 ESDHC 3 */ + esdhc@50020000 { + compatible = "fsl,imx53-esdhc"; + reg = <0x50020000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <3>; + status = "disabled"; + }; + + /* 50024000 0x4000 ESDHC 4 */ + esdhc@50024000 { + compatible = "fsl,imx53-esdhc"; + reg = <0x50024000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <4>; + status = "disabled"; + }; + + /* 50028000 0x4000 SPDIF */ + /* 91 SPDIF */ + + /* 50030000 0x4000 PATA (PORT UDMA) irq70 */ + + /* 50034000 0x4000 SLM */ + /* 50038000 0x4000 HSI2C */ + /* 64 HS-I2C */ + /* 5003C000 0x4000 SPBA */ + }; + + /* 73F80000 0x4000 USBOH3 */ + /* irq14 USBOH3 USB Host 1 */ + /* irq16 USBOH3 USB Host 2 */ + /* irq17 USBOH3 USB Host 3 */ + /* irq18 USBOH3 USB OTG */ + usb1: usb@53F80000 { + compatible = "fsl,usb-4core"; + reg = <0x53f80000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <18 14 16 17>; + }; + + /* 53F98000 0x4000 WDOG1 */ + wdog@53f98000 { + compatible = "fsl,imx53-wdt"; + reg = <0x53f98000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <58>; + status = "disabled"; + }; + + /* 53F9C000 0x4000 WDOG2 (TZ) */ + wdog@53f9c000 { + compatible = "fsl,imx53-wdt"; + reg = <0x53f9c000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <59>; + status = "disabled"; + }; + + /* 53F94000 0x4000 KPP */ + keyboard@53f94000 { + compatible = "fsl,imx53-kpp"; + reg = <0x53f94000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <60>; + status = "disabled"; + }; + + /* 53FA0000 0x4000 GPT */ + timer@53fa0000 { + compatible = "fsl,imx53-gpt"; + reg = <0x53fa0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <39>; + status = "disabled"; + }; + + /* 53FA4000 0x4000 SRTC */ + + rtc@53fa4000 { + compatible = "fsl,imx53-srtc"; + reg = <0x53fa4000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <24 25>; + status = "disabled"; + }; + + /* 53FA8000 0x4000 IOMUXC */ + iomux@53fa8000 { + compatible = "fsl,imx53-iomux"; + reg = <0x53fa8000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <7>; + }; + + /* 53FAC000 0x4000 EPIT1 */ + epit1: timer@53fac000 { + compatible = "fsl,imx53-epit"; + reg = <0x53fac000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <40>; + status = "disabled"; + }; + + /* 53FB0000 0x4000 EPIT2 */ + epit2: timer@53fb0000 { + compatible = "fsl,imx53-epit"; + reg = <0x53fb0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <41>; + status = "disabled"; + }; + + /* 53FB4000 0x4000 PWM1 */ + pwm@53fb4000 { + compatible = "fsl,imx53-pwm"; + reg = <0x53fb4000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <61>; + status = "disabled"; + }; + + /* 53FB8000 0x4000 PWM2 */ + pwm@53fb8000 { + compatible = "fsl,imx53-pwm"; + reg = <0x53fb8000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <94>; + status = "disabled"; + }; + + /* 53FBC000 0x4000 UART 1 */ + uart1: serial@53fbc000 { + compatible = "fsl,imx53-uart", "fsl,imx-uart"; + reg = <0x53fbc000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <31>; + status = "disabled"; + }; + + /* 53FC0000 0x4000 UART 2 */ + uart2: serial@53fc0000 { + compatible = "fsl,imx53-uart", "fsl,imx-uart"; + reg = <0x53fc0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <32>; + status = "disabled"; + }; + + /* 53FC0000 0x4000 UART 4 */ + uart4: serial@53ff0000 { + compatible = "fsl,imx53-uart", "fsl,imx-uart"; + reg = <0x53ff0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <13>; + status = "disabled"; + }; + + + + /* 53FC4000 0x4000 USBOH3 */ + /* NOTYET + usb@53fc4000 { + compatible = "fsl,imx53-otg"; + reg = <0x53fc4000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <>; + status = "disabled"; + }; + */ + /* 53FD0000 0x4000 SRC */ + reset@53fd0000 { + compatible = "fsl,imx53-src"; + reg = <0x53fd0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <75>; + status = "disabled"; + }; + /* 53FD8000 0x4000 GPC */ + power@53fd8000 { + compatible = "fsl,imx53-gpc"; + reg = <0x53fd8000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <73 74>; + status = "disabled"; + }; + + /* 53FE8000 0x4000 PATA (PORT PIO) */ + /* 70 PATA Parallel ATA host controller interrupt */ + ide@53fe8000 { + compatible = "fsl,imx53-ata"; + reg = <0x83fe0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <70>; + status = "disabled"; + }; + + }; + + aips@60000000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* 53FC0000 0x4000 UART 5 */ + uart5: serial@63f90000 { + compatible = "fsl,imx53-uart", "fsl,imx-uart"; + reg = <0x63f90000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <32>; + status = "disabled"; + }; + + /* 63F94000 0x4000 AHBMAX */ + /* 63F98000 0x4000 IIM */ + /* + * 69 IIM Interrupt request to the processor. + * Indicates to the processor that program or + * explicit. + */ + /* 63F9C000 0x4000 CSU */ + /* + * 27 CSU Interrupt Request 1. Indicates to the + * processor that one or more alarm inputs were. + */ + + /* 63FA0000 0x4000 TIGERP_PLATFORM_NE_32K_256K */ + /* irq76 Neon Monitor Interrupt */ + /* irq77 Performance Unit Interrupt */ + /* irq78 CTI IRQ */ + /* irq79 Debug Interrupt, Cross-Trigger Interface 1 */ + /* irq80 Debug Interrupt, Cross-Trigger Interface 1 */ + /* irq89 Debug Interrupt, Cross-Trigger Interface 2 */ + /* irq98 Debug Interrupt, Cross-Trigger Interface 3 */ + + /* 63FA4000 0x4000 OWIRE irq88 */ + /* 63FA8000 0x4000 FIRI irq93 */ + /* 63FAC000 0x4000 eCSPI2 */ + ecspi@63fac000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-ecspi"; + reg = <0x63fac000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <37>; + status = "disabled"; + }; + + /* 63FB0000 0x4000 SDMA */ + sdma@63fb0000 { + compatible = "fsl,imx53-sdma"; + reg = <0x63fb0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <6>; + }; + + /* 63FB4000 0x4000 SCC */ + /* 21 SCC Security Monitor High Priority Interrupt. */ + /* 22 SCC Secure (TrustZone) Interrupt. */ + /* 23 SCC Regular (Non-Secure) Interrupt. */ + + /* 63FB8000 0x4000 ROMCP */ + /* 63FBC000 0x4000 RTIC */ + /* + * 26 RTIC RTIC (Trust Zone) Interrupt Request. + * Indicates that the RTIC has completed hashing the + */ + + /* 63FC0000 0x4000 CSPI */ + cspi@63fc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-cspi"; + reg = <0x63fc0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <38>; + status = "disabled"; + }; + + /* 63FC4000 0x4000 I2C2 */ + i2c@63fc4000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-i2c", "fsl,imx1-i2c", "fsl,imx-i2c"; + reg = <0x63fc4000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <63>; + status = "disabled"; + }; + + /* 63FC8000 0x4000 I2C1 */ + i2c@63fc8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx53-i2c", "fsl,imx1-i2c", "fsl,imx-i2c"; + reg = <0x63fc8000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <62>; + status = "disabled"; + }; + + /* 63FCC000 0x4000 SSI1 */ + /* 29 SSI1 SSI-1 Interrupt Request */ + SSI1: ssi@63fcc000 { + compatible = "fsl,imx53-ssi"; + reg = <0x63fcc000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <29>; + status = "disabled"; + }; + + /* 63FD0000 0x4000 AUDMUX */ + audmux@63fd4000 { + compatible = "fsl,imx53-audmux"; + reg = <0x63fd4000 0x4000>; + status = "disabled"; + }; + + /* 63FD8000 0x4000 EXTMC */ + /* 8 EXTMC (NFC) */ + /* 15 EXTMC */ + /* 97 EXTMC Boot sequence completed interrupt */ + /* + * 101 EMI Indicates all pages have been transferred + * to NFC during an auto program operation. + */ + + /* 83FE4000 0x4000 SIM */ + /* 67 SIM intr composed of oef, xte, sdi1, and sdi0 */ + /* 68 SIM intr composed of tc, etc, tfe, and rdrf */ + + /* 63FD_C000 0x4000 apb2ip_pl301_2x2 */ + /* 63FE_0000 0x4000 apb2ip_pl301_4x1 */ + /* 63FE4000 0x4000 MLB */ + /* 63FE8000 0x4000 SSI3 */ + /* 96 SSI3 SSI-3 Interrupt Request */ + SSI3: ssi@63fe8000 { + compatible = "fsl,imx51-ssi"; + reg = <0x63fe8000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <96>; + status = "disabled"; + }; + + /* 63FEC000 0x4000 FEC */ + ethernet@63fec000 { + compatible = "fsl,imx53-fec"; + reg = <0x63fec000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <87>; + status = "disabled"; + }; + + /* 63FF0000 0x4000 TVE */ + /* 92 TVE */ + /* 63FF4000 0x4000 VPU */ + /* 9 VPU */ + /* 100 VPU Idle interrupt from VPU */ + + /* 63FF8000 0x4000 SAHARA */ + /* 19 SAHARA SAHARA host 0 (TrustZone) Intr */ + /* 20 SAHARA SAHARA host 1 (non-TrustZone) Intr */ + }; + }; + + localbus@18000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges; + + vga: ipu3@18000000 { + compatible = "fsl,ipu3"; + reg = < + 0x18000000 0x08000 /* CM */ + 0x18008000 0x08000 /* IDMAC */ + 0x18018000 0x08000 /* DP */ + 0x18020000 0x08000 /* IC */ + 0x18028000 0x08000 /* IRT */ + 0x18030000 0x08000 /* CSI0 */ + 0x18038000 0x08000 /* CSI1 */ + 0x18040000 0x08000 /* DI0 */ + 0x18048000 0x08000 /* DI1 */ + 0x18050000 0x08000 /* SMFC */ + 0x18058000 0x08000 /* DC */ + 0x18060000 0x08000 /* DMFC */ + 0x18068000 0x08000 /* VDI */ + 0x19000000 0x20000 /* CPMEM */ + 0x19020000 0x20000 /* LUT */ + 0x19040000 0x20000 /* SRM */ + 0x19060000 0x20000 /* TPM */ + 0x19080000 0x20000 /* DCTMPL */ + >; + interrupt-parent = <&tzic>; + interrupts = < + 10 /* IPUEX Error */ + 11 /* IPUEX Sync */ + >; + status = "disabled"; + }; + }; +}; + +/* + +TODO: Not mapped interrupts + +5 DAP +84 GPU2D (OpenVG) general interrupt +85 GPU2D (OpenVG) busy signal (for S/W power gating feasibility) +12 GPU3D +102 GPU3D Idle interrupt from GPU3D (for S/W power gating) +90 SJC +*/ diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h index da2bc7c..303d37f 100644 --- a/sys/bsm/audit_kevents.h +++ b/sys/bsm/audit_kevents.h @@ -589,6 +589,7 @@ #define AUE_POSIX_OPENPT 43185 /* FreeBSD. */ #define AUE_CAP_NEW 43186 /* TrustedBSD. */ #define AUE_CAP_RIGHTS_GET 43187 /* TrustedBSD. */ +#define AUE_CAP_GETRIGHTS AUE_CAP_RIGHTS_GET #define AUE_CAP_ENTER 43188 /* TrustedBSD. */ #define AUE_CAP_GETMODE 43189 /* TrustedBSD. */ #define AUE_POSIX_SPAWN 43190 /* Darwin. */ diff --git a/sys/bsm/audit_record.h b/sys/bsm/audit_record.h index 706c6f3..7e6074f 100644 --- a/sys/bsm/audit_record.h +++ b/sys/bsm/audit_record.h @@ -34,6 +34,7 @@ #define _BSM_AUDIT_RECORD_H_ #include <sys/time.h> /* struct timeval */ +#include <sys/caprights.h> /* cap_rights_t */ /* * Token type identifiers. @@ -126,6 +127,8 @@ #define AUT_SOCKINET128 0x81 /* XXX */ #define AUT_SOCKUNIX 0x82 /* XXX */ +#define AUT_RIGHTS 0x83 + /* print values for the arbitrary token */ #define AUP_BINARY 0 #define AUP_OCTAL 1 @@ -248,6 +251,7 @@ token_t *au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, au_tid_addr_t *tid); token_t *au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); +token_t *au_to_rights(cap_rights_t *rightsp); token_t *au_to_return(char status, uint32_t ret); token_t *au_to_return32(char status, uint32_t ret); token_t *au_to_return64(char status, uint64_t ret); diff --git a/sys/cam/cam_debug.h b/sys/cam/cam_debug.h index e072ec1..ecfeb3a 100644 --- a/sys/cam/cam_debug.h +++ b/sys/cam/cam_debug.h @@ -99,6 +99,17 @@ extern u_int32_t cam_debug_delay; DELAY(cam_debug_delay); \ } +#define CAM_DEBUG_DEV(dev, flag, printfargs) \ + if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ + && (cam_dpath != NULL) \ + && (xpt_path_comp_dev(cam_dpath, dev) >= 0) \ + && (xpt_path_comp_dev(cam_dpath, dev) < 2)) { \ + xpt_print_device(dev); \ + printf printfargs; \ + if (cam_debug_delay != 0) \ + DELAY(cam_debug_delay); \ + } + #define CAM_DEBUG_PRINT(flag, printfargs) \ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \ printf("cam_debug: "); \ diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index d6f7746..b230c6c 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1115,6 +1115,7 @@ cam_freeze_devq(struct cam_path *path) { struct ccb_hdr ccb_h; + CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_freeze_devq\n")); xpt_setup_ccb(&ccb_h, path, /*priority*/1); ccb_h.func_code = XPT_NOOP; ccb_h.flags = CAM_DEV_QFREEZE; @@ -1128,6 +1129,8 @@ cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, { struct ccb_relsim crs; + CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_release_devq(%u, %u, %u, %d)\n", + relsim_flags, openings, arg, getcount_only)); xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index da0b4da..e50b0ad 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -3561,6 +3561,40 @@ xpt_path_comp(struct cam_path *path1, struct cam_path *path2) return (retval); } +int +xpt_path_comp_dev(struct cam_path *path, struct cam_ed *dev) +{ + int retval = 0; + + if (path->bus != dev->target->bus) { + if (path->bus->path_id == CAM_BUS_WILDCARD) + retval = 1; + else if (dev->target->bus->path_id == CAM_BUS_WILDCARD) + retval = 2; + else + return (-1); + } + if (path->target != dev->target) { + if (path->target->target_id == CAM_TARGET_WILDCARD) { + if (retval == 0) + retval = 1; + } else if (dev->target->target_id == CAM_TARGET_WILDCARD) + retval = 2; + else + return (-1); + } + if (path->device != dev) { + if (path->device->lun_id == CAM_LUN_WILDCARD) { + if (retval == 0) + retval = 1; + } else if (dev->lun_id == CAM_LUN_WILDCARD) + retval = 2; + else + return (-1); + } + return (retval); +} + void xpt_print_path(struct cam_path *path) { @@ -3594,6 +3628,21 @@ xpt_print_path(struct cam_path *path) } void +xpt_print_device(struct cam_ed *device) +{ + + if (device == NULL) + printf("(nopath): "); + else { + printf("(noperiph:%s%d:%d:%d:%d): ", device->sim->sim_name, + device->sim->unit_number, + device->sim->bus_id, + device->target->target_id, + device->lun_id); + } +} + +void xpt_print(struct cam_path *path, const char *fmt, ...) { va_list ap; @@ -4114,6 +4163,8 @@ xpt_freeze_devq(struct cam_path *path, u_int count) struct cam_ed *dev = path->device; mtx_assert(path->bus->sim->mtx, MA_OWNED); + CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_freeze_devq() %u->%u\n", + dev->ccbq.queue.qfrozen_cnt, dev->ccbq.queue.qfrozen_cnt + count)); dev->ccbq.queue.qfrozen_cnt += count; /* Remove frozen device from sendq. */ if (device_is_queued(dev)) { @@ -4138,6 +4189,7 @@ xpt_release_devq_timeout(void *arg) struct cam_ed *device; device = (struct cam_ed *)arg; + CAM_DEBUG_DEV(device, CAM_DEBUG_TRACE, ("xpt_release_devq_timeout\n")); xpt_release_devq_device(device, /*count*/1, /*run_queue*/TRUE); } @@ -4146,6 +4198,8 @@ xpt_release_devq(struct cam_path *path, u_int count, int run_queue) { mtx_assert(path->bus->sim->mtx, MA_OWNED); + CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_release_devq(%d, %d)\n", + count, run_queue)); xpt_release_devq_device(path->device, count, run_queue); } @@ -4153,6 +4207,9 @@ void xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue) { + CAM_DEBUG_DEV(dev, CAM_DEBUG_TRACE, + ("xpt_release_devq_device(%d, %d) %u->%u\n", count, run_queue, + dev->ccbq.queue.qfrozen_cnt, dev->ccbq.queue.qfrozen_cnt - count)); if (count > dev->ccbq.queue.qfrozen_cnt) { #ifdef INVARIANTS printf("xpt_release_devq(): requested %u > present %u\n", diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h index 492fa3a..97933b9 100644 --- a/sys/cam/cam_xpt.h +++ b/sys/cam/cam_xpt.h @@ -35,6 +35,7 @@ /* Forward Declarations */ union ccb; struct cam_periph; +struct cam_ed; struct cam_sim; /* @@ -89,7 +90,10 @@ void xpt_path_counts(struct cam_path *path, uint32_t *bus_ref, uint32_t *device_ref); int xpt_path_comp(struct cam_path *path1, struct cam_path *path2); +int xpt_path_comp_dev(struct cam_path *path, + struct cam_ed *dev); void xpt_print_path(struct cam_path *path); +void xpt_print_device(struct cam_ed *device); void xpt_print(struct cam_path *path, const char *fmt, ...); int xpt_path_string(struct cam_path *path, char *str, size_t str_len); diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 8ee47f9..913951e 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -3851,4 +3851,31 @@ scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries, timeout); } +void +scsi_sanitize(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t byte2, u_int16_t control, + u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, + u_int32_t timeout) +{ + struct scsi_sanitize *scsi_cmd; + + scsi_cmd = (struct scsi_sanitize *)&csio->cdb_io.cdb_bytes; + scsi_cmd->opcode = SANITIZE; + scsi_cmd->byte2 = byte2; + scsi_cmd->control = control; + scsi_ulto2b(dxfer_len, scsi_cmd->length); + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE, + tag_action, + data_ptr, + dxfer_len, + sense_len, + sizeof(*scsi_cmd), + timeout); +} + #endif /* _KERNEL */ diff --git a/sys/cam/scsi/scsi_da.h b/sys/cam/scsi/scsi_da.h index 5799238..4fbd725 100644 --- a/sys/cam/scsi/scsi_da.h +++ b/sys/cam/scsi/scsi_da.h @@ -116,6 +116,31 @@ struct scsi_read_defect_data_10 u_int8_t control; }; +struct scsi_sanitize +{ + u_int8_t opcode; + u_int8_t byte2; +#define SSZ_SERVICE_ACTION_OVERWRITE 0x01 +#define SSZ_SERVICE_ACTION_BLOCK_ERASE 0x02 +#define SSZ_SERVICE_ACTION_CRYPTO_ERASE 0x03 +#define SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE 0x1F +#define SSZ_UNRESTRICTED_EXIT 0x20 +#define SSZ_IMMED 0x80 + u_int8_t reserved[5]; + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_sanitize_parameter_list +{ + u_int8_t byte1; +#define SSZPL_INVERT 0x80 + u_int8_t reserved; + u_int8_t length[2]; + /* Variable length initialization pattern. */ +#define SSZPL_MAX_PATTERN_LENGTH 65535 +}; + struct scsi_read_defect_data_12 { u_int8_t opcode; @@ -156,6 +181,7 @@ struct scsi_read_defect_data_12 #define WRITE_AND_VERIFY 0x2e #define VERIFY 0x2f #define READ_DEFECT_DATA_10 0x37 +#define SANITIZE 0x48 #define READ_DEFECT_DATA_12 0xb7 struct format_defect_list_header @@ -508,6 +534,12 @@ void scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout); +void scsi_sanitize(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t byte2, u_int16_t control, + u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, + u_int32_t timeout); + #endif /* !_KERNEL */ __END_DECLS diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c index 2e51030..6917fff 100644 --- a/sys/cam/scsi/scsi_enc_ses.c +++ b/sys/cam/scsi/scsi_enc_ses.c @@ -567,8 +567,8 @@ ses_cache_free_elm_addlstatus(enc_softc_t *enc, enc_cache_t *cache) return; for (cur_elm = cache->elm_map, - last_elm = &cache->elm_map[cache->nelms - 1]; - cur_elm <= last_elm; cur_elm++) { + last_elm = &cache->elm_map[cache->nelms]; + cur_elm != last_elm; cur_elm++) { ses_element_t *elmpriv; elmpriv = cur_elm->elm_private; @@ -598,8 +598,8 @@ ses_cache_free_elm_descs(enc_softc_t *enc, enc_cache_t *cache) return; for (cur_elm = cache->elm_map, - last_elm = &cache->elm_map[cache->nelms - 1]; - cur_elm <= last_elm; cur_elm++) { + last_elm = &cache->elm_map[cache->nelms]; + cur_elm != last_elm; cur_elm++) { ses_element_t *elmpriv; elmpriv = cur_elm->elm_private; @@ -644,8 +644,8 @@ ses_cache_free_elm_map(enc_softc_t *enc, enc_cache_t *cache) ses_cache_free_elm_descs(enc, cache); ses_cache_free_elm_addlstatus(enc, cache); for (cur_elm = cache->elm_map, - last_elm = &cache->elm_map[cache->nelms - 1]; - cur_elm <= last_elm; cur_elm++) { + last_elm = &cache->elm_map[cache->nelms]; + cur_elm != last_elm; cur_elm++) { ENC_FREE_AND_NULL(cur_elm->elm_private); } @@ -717,8 +717,8 @@ ses_cache_clone(enc_softc_t *enc, enc_cache_t *src, enc_cache_t *dst) dst->elm_map = ENC_MALLOCZ(dst->nelms * sizeof(enc_element_t)); memcpy(dst->elm_map, src->elm_map, dst->nelms * sizeof(enc_element_t)); for (dst_elm = dst->elm_map, src_elm = src->elm_map, - last_elm = &src->elm_map[src->nelms - 1]; - src_elm <= last_elm; src_elm++, dst_elm++) { + last_elm = &src->elm_map[src->nelms]; + src_elm != last_elm; src_elm++, dst_elm++) { dst_elm->elm_private = ENC_MALLOCZ(sizeof(ses_element_t)); memcpy(dst_elm->elm_private, src_elm->elm_private, @@ -1555,6 +1555,18 @@ ses_process_status(enc_softc_t *enc, struct enc_fsm_state *state, ENC_VLOG(enc, "Enclosure Status Page Too Long\n"); goto out; } + + /* Check for simple enclosure reporting short enclosure status. */ + if (length >= 4 && page->hdr.page_code == SesShortStatus) { + ENC_DLOG(enc, "Got Short Enclosure Status page\n"); + ses->ses_flags &= ~(SES_FLAG_ADDLSTATUS | SES_FLAG_DESC); + ses_cache_free(enc, enc_cache); + enc_cache->enc_status = page->hdr.page_specific_flags; + enc_update_request(enc, SES_PUBLISH_CACHE); + err = 0; + goto out; + } + /* Make sure the length contains at least one header and status */ if (length < (sizeof(*page) + sizeof(*page->elements))) { ENC_VLOG(enc, "Enclosure Status Page Too Short\n"); diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h index 0b8f875..5f83082 100644 --- a/sys/cddl/compat/opensolaris/sys/file.h +++ b/sys/cddl/compat/opensolaris/sys/file.h @@ -39,11 +39,11 @@ typedef struct file file_t; #include <sys/capability.h> static __inline file_t * -getf(int fd, cap_rights_t rights) +getf(int fd, cap_rights_t *rightsp) { struct file *fp; - if (fget(curthread, fd, rights, &fp) == 0) + if (fget(curthread, fd, rightsp, &fp) == 0) return (fp); return (NULL); } @@ -54,7 +54,7 @@ releasef(int fd) struct file *fp; /* No CAP_ rights required, as we're only releasing. */ - if (fget(curthread, fd, 0, &fp) == 0) { + if (fget(curthread, fd, NULL, &fp) == 0) { fdrop(fp, curthread); fdrop(fp, curthread); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c index f2f7139..50a1e82 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c @@ -32,6 +32,9 @@ #include <sys/vdev_impl.h> #include <sys/zio.h> +SYSCTL_DECL(_vfs_zfs); +SYSCTL_NODE(_vfs_zfs, OID_AUTO, metaslab, CTLFLAG_RW, 0, "ZFS metaslab"); + /* * Allow allocations to switch to gang blocks quickly. We do this to * avoid having to load lots of space_maps in a given txg. There are, @@ -46,6 +49,10 @@ uint64_t metaslab_aliquot = 512ULL << 10; uint64_t metaslab_gang_bang = SPA_MAXBLOCKSIZE + 1; /* force gang blocks */ +TUNABLE_QUAD("vfs.zfs.metaslab.gang_bang", &metaslab_gang_bang); +SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, gang_bang, CTLFLAG_RWTUN, + &metaslab_gang_bang, 0, + "Force gang block allocation for blocks larger than or equal to this value"); /* * The in-core space map representation is more compact than its on-disk form. @@ -61,17 +68,19 @@ int zfs_condense_pct = 200; * allocations on that device. */ int zfs_mg_alloc_failures = 0; - -SYSCTL_DECL(_vfs_zfs); -SYSCTL_INT(_vfs_zfs, OID_AUTO, mg_alloc_failures, CTLFLAG_RDTUN, +TUNABLE_INT("vfs.zfs.mg_alloc_failures", &zfs_mg_alloc_failures); +SYSCTL_INT(_vfs_zfs, OID_AUTO, mg_alloc_failures, CTLFLAG_RWTUN, &zfs_mg_alloc_failures, 0, "Number of allowed allocation failures per vdev"); -TUNABLE_INT("vfs.zfs.mg_alloc_failures", &zfs_mg_alloc_failures); /* * Metaslab debugging: when set, keeps all space maps in core to verify frees. */ static int metaslab_debug = 0; +TUNABLE_INT("vfs.zfs.metaslab.debug", &metaslab_debug); +SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, debug, CTLFLAG_RWTUN, &metaslab_debug, + 0, + "Metaslab debugging: when set, keeps all space maps in core to verify frees"); /* * Minimum size which forces the dynamic allocator to change @@ -80,6 +89,11 @@ static int metaslab_debug = 0; * aggressive strategy (i.e search by size rather than offset). */ uint64_t metaslab_df_alloc_threshold = SPA_MAXBLOCKSIZE; +TUNABLE_QUAD("vfs.zfs.metaslab.df_alloc_threshold", + &metaslab_df_alloc_threshold); +SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, df_alloc_threshold, CTLFLAG_RWTUN, + &metaslab_df_alloc_threshold, 0, + "Minimum size which forces the dynamic allocator to change it's allocation strategy"); /* * The minimum free space, in percent, which must be available @@ -88,22 +102,37 @@ uint64_t metaslab_df_alloc_threshold = SPA_MAXBLOCKSIZE; * switch to using best-fit allocations. */ int metaslab_df_free_pct = 4; +TUNABLE_INT("vfs.zfs.metaslab.df_free_pct", &metaslab_df_free_pct); +SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, df_free_pct, CTLFLAG_RWTUN, + &metaslab_df_free_pct, 0, + "The minimum free space, in percent, which must be available in a space map to continue allocations in a first-fit fashion"); /* * A metaslab is considered "free" if it contains a contiguous * segment which is greater than metaslab_min_alloc_size. */ uint64_t metaslab_min_alloc_size = DMU_MAX_ACCESS; +TUNABLE_QUAD("vfs.zfs.metaslab.min_alloc_size", + &metaslab_min_alloc_size); +SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, min_alloc_size, CTLFLAG_RWTUN, + &metaslab_min_alloc_size, 0, + "A metaslab is considered \"free\" if it contains a contiguous segment which is greater than vfs.zfs.metaslab.min_alloc_size"); /* * Max number of space_maps to prefetch. */ int metaslab_prefetch_limit = SPA_DVAS_PER_BP; +TUNABLE_INT("vfs.zfs.metaslab.prefetch_limit", &metaslab_prefetch_limit); +SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, prefetch_limit, CTLFLAG_RWTUN, + &metaslab_prefetch_limit, 0, "Maximum number of space_maps to prefetch"); /* * Percentage bonus multiplier for metaslabs that are in the bonus area. */ int metaslab_smo_bonus_pct = 150; +TUNABLE_INT("vfs.zfs.metaslab.smo_bonus_pct", &metaslab_smo_bonus_pct); +SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, smo_bonus_pct, CTLFLAG_RWTUN, + &metaslab_smo_bonus_pct, 0, "Maximum number of space_maps to prefetch"); /* * Should we be willing to write data to degraded vdevs? diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 10456f8..e9fba26 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -4005,6 +4005,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) char *origin = NULL; char *tosnap; char tofs[ZFS_MAXNAMELEN]; + cap_rights_t rights; boolean_t first_recvd_props = B_FALSE; if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || @@ -4022,7 +4023,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) return (error); fd = zc->zc_cookie; - fp = getf(fd, CAP_PREAD); + fp = getf(fd, cap_rights_init(&rights, CAP_PREAD)); if (fp == NULL) { nvlist_free(props); return (SET_ERROR(EBADF)); @@ -4260,7 +4261,11 @@ zfs_ioc_send(zfs_cmd_t *zc) dsl_dataset_rele(tosnap, FTAG); dsl_pool_rele(dp, FTAG); } else { - file_t *fp = getf(zc->zc_cookie, CAP_WRITE); + file_t *fp; + cap_rights_t rights; + + fp = getf(zc->zc_cookie, + cap_rights_init(&rights, CAP_WRITE)); if (fp == NULL) return (SET_ERROR(EBADF)); @@ -4851,10 +4856,11 @@ static int zfs_ioc_diff(zfs_cmd_t *zc) { file_t *fp; + cap_rights_t rights; offset_t off; int error; - fp = getf(zc->zc_cookie, CAP_WRITE); + fp = getf(zc->zc_cookie, cap_rights_init(&rights, CAP_WRITE)); if (fp == NULL) return (SET_ERROR(EBADF)); @@ -5214,6 +5220,7 @@ zfs_ioc_unjail(zfs_cmd_t *zc) static int zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl) { + cap_rights_t rights; int error; offset_t off; char *fromname = NULL; @@ -5225,7 +5232,7 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl) (void) nvlist_lookup_string(innvl, "fromsnap", &fromname); - file_t *fp = getf(fd, CAP_READ); + file_t *fp = getf(fd, cap_rights_init(&rights, CAP_READ)); if (fp == NULL) return (SET_ERROR(EBADF)); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c index 05252cb..6a90b9c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c @@ -122,10 +122,11 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp) { file_t *fp, *tmpfp; zfs_onexit_t *zo; + cap_rights_t rights; void *data; int error; - fp = getf(fd, CAP_NONE); + fp = getf(fd, cap_rights_init(&rights)); if (fp == NULL) return (SET_ERROR(EBADF)); diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c index d22f207..d58cf92 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c @@ -213,8 +213,8 @@ dtrace_gethrtime_init(void *arg) CPU_SET(pc->pc_cpuid, &map); smp_rendezvous_cpus(map, NULL, - dtrace_gethrtime_init_cpu, - smp_no_rendevous_barrier, (void *)(uintptr_t) i); + dtrace_gethrtime_init_cpu, + smp_no_rendevous_barrier, (void *)(uintptr_t) i); timebase_skew[i] = tgt_cpu_tsc - hst_cpu_tsc; } @@ -247,7 +247,7 @@ dtrace_gethrtime() lo = timebase; hi = timebase >> 32; return (((lo * nsec_scale) >> SCALE_SHIFT) + - ((hi * nsec_scale) << (32 - SCALE_SHIFT))); + ((hi * nsec_scale) << (32 - SCALE_SHIFT))); } uint64_t @@ -280,34 +280,34 @@ dtrace_trap(struct trapframe *frame, u_int type) * All the rest will be handled in the usual way. */ switch (type) { - /* Page fault. */ - case EXC_DSI: - case EXC_DSE: - /* Flag a bad address. */ - cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR; - cpu_core[curcpu].cpuc_dtrace_illval = frame->cpu.aim.dar; - - /* - * Offset the instruction pointer to the instruction - * following the one causing the fault. - */ - frame->srr0 += sizeof(int); - return (1); - case EXC_ISI: - case EXC_ISE: - /* Flag a bad address. */ - cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR; - cpu_core[curcpu].cpuc_dtrace_illval = frame->srr0; - - /* - * Offset the instruction pointer to the instruction - * following the one causing the fault. - */ - frame->srr0 += sizeof(int); - return (1); - default: - /* Handle all other traps in the usual way. */ - break; + /* Page fault. */ + case EXC_DSI: + case EXC_DSE: + /* Flag a bad address. */ + cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR; + cpu_core[curcpu].cpuc_dtrace_illval = frame->cpu.aim.dar; + + /* + * Offset the instruction pointer to the instruction + * following the one causing the fault. + */ + frame->srr0 += sizeof(int); + return (1); + case EXC_ISI: + case EXC_ISE: + /* Flag a bad address. */ + cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR; + cpu_core[curcpu].cpuc_dtrace_illval = frame->srr0; + + /* + * Offset the instruction pointer to the instruction + * following the one causing the fault. + */ + frame->srr0 += sizeof(int); + return (1); + default: + /* Handle all other traps in the usual way. */ + break; } } @@ -321,29 +321,29 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, { dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state, - (uintptr_t)epid, - (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs); + (uintptr_t)epid, + (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs); } static int dtrace_invop_start(struct trapframe *frame) { switch (dtrace_invop(frame->srr0, (uintptr_t *)frame, frame->fixreg[3])) { - case DTRACE_INVOP_JUMP: - break; - case DTRACE_INVOP_BCTR: - frame->srr0 = frame->ctr; - break; - case DTRACE_INVOP_BLR: - frame->srr0 = frame->lr; - break; - case DTRACE_INVOP_MFLR_R0: - frame->fixreg[0] = frame->lr; - frame->srr0 = frame->srr0 + 4; - break; - default: - return (-1); - break; + case DTRACE_INVOP_JUMP: + break; + case DTRACE_INVOP_BCTR: + frame->srr0 = frame->ctr; + break; + case DTRACE_INVOP_BLR: + frame->srr0 = frame->lr; + break; + case DTRACE_INVOP_MFLR_R0: + frame->fixreg[0] = frame->lr; + frame->srr0 = frame->srr0 + 4; + break; + default: + return (-1); + break; } return (0); diff --git a/sys/compat/freebsd32/freebsd32_capability.c b/sys/compat/freebsd32/freebsd32_capability.c index e17c394..b23cf95 100644 --- a/sys/compat/freebsd32/freebsd32_capability.c +++ b/sys/compat/freebsd32/freebsd32_capability.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <security/audit/audit.h> -#include <compat/freebsd32/freebsd32_misc.h> #include <compat/freebsd32/freebsd32_proto.h> #ifdef CAPABILITIES @@ -50,17 +49,6 @@ __FBSDID("$FreeBSD$"); MALLOC_DECLARE(M_FILECAPS); int -freebsd32_cap_rights_limit(struct thread *td, - struct freebsd32_cap_rights_limit_args *uap) -{ - struct cap_rights_limit_args ap; - - ap.fd = uap->fd; - ap.rights = PAIR32TO64(uint64_t, uap->rights); - return (sys_cap_rights_limit(td, &ap)); -} - -int freebsd32_cap_ioctls_limit(struct thread *td, struct freebsd32_cap_ioctls_limit_args *uap) { @@ -148,14 +136,6 @@ out: #else /* !CAPABILITIES */ int -freebsd32_cap_rights_limit(struct thread *td, - struct freebsd32_cap_rights_limit_args *uap) -{ - - return (ENOSYS); -} - -int freebsd32_cap_ioctls_limit(struct thread *td, struct freebsd32_cap_ioctls_limit_args *uap) { diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c index 81f5c8e..1f90e58 100644 --- a/sys/compat/freebsd32/freebsd32_ioctl.c +++ b/sys/compat/freebsd32/freebsd32_ioctl.c @@ -353,9 +353,11 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) caddr_t data; }*/ ; struct file *fp; + cap_rights_t rights; int error; - if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { fdrop(fp, td); diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 16d1205..a3cf5cf 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1650,6 +1650,7 @@ freebsd32_do_sendfile(struct thread *td, struct uio *hdr_uio, *trl_uio; struct iovec32 *iov32; struct file *fp; + cap_rights_t rights; off_t offset; int error; @@ -1686,8 +1687,10 @@ freebsd32_do_sendfile(struct thread *td, AUDIT_ARG_FD(uap->fd); - if ((error = fget_read(td, uap->fd, CAP_PREAD, &fp)) != 0) + if ((error = fget_read(td, uap->fd, + cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) { goto out; + } error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset, uap->nbytes, uap->sbytes, uap->flags, compat ? SFK_COMPAT : 0, td); diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 363aad3..96b9b37 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 254491 2013-08-18 13:37:54Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #ifndef _FREEBSD32_SYSPROTO_H_ @@ -627,12 +627,6 @@ struct freebsd32_wait6_args { char wrusage_l_[PADL_(struct wrusage32 *)]; struct wrusage32 * wrusage; char wrusage_r_[PADR_(struct wrusage32 *)]; char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)]; }; -struct freebsd32_cap_rights_limit_args { - char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; - char rights1_l_[PADL_(uint32_t)]; uint32_t rights1; char rights1_r_[PADR_(uint32_t)]; - char rights2_l_[PADL_(uint32_t)]; uint32_t rights2; char rights2_r_[PADR_(uint32_t)]; -}; #else struct freebsd32_posix_fallocate_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; @@ -658,11 +652,6 @@ struct freebsd32_wait6_args { char wrusage_l_[PADL_(struct wrusage32 *)]; struct wrusage32 * wrusage; char wrusage_r_[PADR_(struct wrusage32 *)]; char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)]; }; -struct freebsd32_cap_rights_limit_args { - char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char rights1_l_[PADL_(uint32_t)]; uint32_t rights1; char rights1_r_[PADR_(uint32_t)]; - char rights2_l_[PADL_(uint32_t)]; uint32_t rights2; char rights2_r_[PADR_(uint32_t)]; -}; #endif struct freebsd32_cap_ioctls_limit_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; @@ -795,12 +784,10 @@ int freebsd32_pselect(struct thread *, struct freebsd32_pselect_args *); int freebsd32_posix_fallocate(struct thread *, struct freebsd32_posix_fallocate_args *); int freebsd32_posix_fadvise(struct thread *, struct freebsd32_posix_fadvise_args *); int freebsd32_wait6(struct thread *, struct freebsd32_wait6_args *); -int freebsd32_cap_rights_limit(struct thread *, struct freebsd32_cap_rights_limit_args *); #else int freebsd32_posix_fallocate(struct thread *, struct freebsd32_posix_fallocate_args *); int freebsd32_posix_fadvise(struct thread *, struct freebsd32_posix_fadvise_args *); int freebsd32_wait6(struct thread *, struct freebsd32_wait6_args *); -int freebsd32_cap_rights_limit(struct thread *, struct freebsd32_cap_rights_limit_args *); #endif int freebsd32_cap_ioctls_limit(struct thread *, struct freebsd32_cap_ioctls_limit_args *); int freebsd32_cap_ioctls_get(struct thread *, struct freebsd32_cap_ioctls_get_args *); @@ -1199,11 +1186,9 @@ int freebsd7_freebsd32_shmctl(struct thread *, struct freebsd7_freebsd32_shmctl_ #define FREEBSD32_SYS_AUE_freebsd32_posix_fallocate AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_posix_fadvise AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_wait6 AUE_WAIT6 -#define FREEBSD32_SYS_AUE_freebsd32_cap_rights_limit AUE_CAP_RIGHTS_LIMIT #define FREEBSD32_SYS_AUE_freebsd32_posix_fallocate AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_posix_fadvise AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_wait6 AUE_WAIT6 -#define FREEBSD32_SYS_AUE_freebsd32_cap_rights_limit AUE_CAP_RIGHTS_LIMIT #define FREEBSD32_SYS_AUE_freebsd32_cap_ioctls_limit AUE_CAP_IOCTLS_LIMIT #define FREEBSD32_SYS_AUE_freebsd32_cap_ioctls_get AUE_CAP_IOCTLS_GET #define FREEBSD32_SYS_AUE_freebsd32_aio_mlock AUE_NULL diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 8568201..dbbee5b 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 254491 2013-08-18 13:37:54Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #define FREEBSD32_SYS_syscall 0 @@ -420,8 +420,8 @@ #define FREEBSD32_SYS_freebsd32_msgctl 511 #define FREEBSD32_SYS_freebsd32_shmctl 512 #define FREEBSD32_SYS_lpathconf 513 -#define FREEBSD32_SYS_cap_new 514 -#define FREEBSD32_SYS_cap_rights_get 515 + /* 514 is obsolete cap_new */ +#define FREEBSD32_SYS___cap_rights_get 515 #define FREEBSD32_SYS_cap_enter 516 #define FREEBSD32_SYS_cap_getmode 517 #define FREEBSD32_SYS_pdfork 518 @@ -438,11 +438,10 @@ #define FREEBSD32_SYS_freebsd32_posix_fallocate 530 #define FREEBSD32_SYS_freebsd32_posix_fadvise 531 #define FREEBSD32_SYS_freebsd32_wait6 532 -#define FREEBSD32_SYS_freebsd32_cap_rights_limit 533 #define FREEBSD32_SYS_freebsd32_posix_fallocate 530 #define FREEBSD32_SYS_freebsd32_posix_fadvise 531 #define FREEBSD32_SYS_freebsd32_wait6 532 -#define FREEBSD32_SYS_freebsd32_cap_rights_limit 533 +#define FREEBSD32_SYS_cap_rights_limit 533 #define FREEBSD32_SYS_freebsd32_cap_ioctls_limit 534 #define FREEBSD32_SYS_freebsd32_cap_ioctls_get 535 #define FREEBSD32_SYS_cap_fcntls_limit 536 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 734b9fd..3f6cbfc 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 254491 2013-08-18 13:37:54Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ const char *freebsd32_syscallnames[] = { @@ -537,8 +537,8 @@ const char *freebsd32_syscallnames[] = { "freebsd32_msgctl", /* 511 = freebsd32_msgctl */ "freebsd32_shmctl", /* 512 = freebsd32_shmctl */ "lpathconf", /* 513 = lpathconf */ - "cap_new", /* 514 = cap_new */ - "cap_rights_get", /* 515 = cap_rights_get */ + "obs_cap_new", /* 514 = obsolete cap_new */ + "__cap_rights_get", /* 515 = __cap_rights_get */ "cap_enter", /* 516 = cap_enter */ "cap_getmode", /* 517 = cap_getmode */ "pdfork", /* 518 = pdfork */ @@ -557,13 +557,12 @@ const char *freebsd32_syscallnames[] = { "freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */ "freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */ "freebsd32_wait6", /* 532 = freebsd32_wait6 */ - "freebsd32_cap_rights_limit", /* 533 = freebsd32_cap_rights_limit */ #else "freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */ "freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */ "freebsd32_wait6", /* 532 = freebsd32_wait6 */ - "freebsd32_cap_rights_limit", /* 533 = freebsd32_cap_rights_limit */ #endif + "cap_rights_limit", /* 533 = cap_rights_limit */ "freebsd32_cap_ioctls_limit", /* 534 = freebsd32_cap_ioctls_limit */ "freebsd32_cap_ioctls_get", /* 535 = freebsd32_cap_ioctls_get */ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */ diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 1c82a00..00b4153 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 254491 2013-08-18 13:37:54Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #include "opt_compat.h" @@ -574,8 +574,8 @@ struct sysent freebsd32_sysent[] = { { AS(freebsd32_msgctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 511 = freebsd32_msgctl */ { AS(freebsd32_shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 512 = freebsd32_shmctl */ { AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 513 = lpathconf */ - { AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, 0, SY_THR_STATIC }, /* 514 = cap_new */ - { AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 515 = cap_rights_get */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 514 = obsolete cap_new */ + { AS(__cap_rights_get_args), (sy_call_t *)sys___cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 515 = __cap_rights_get */ { 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, 0, SY_THR_STATIC }, /* 516 = cap_enter */ { AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 517 = cap_getmode */ { AS(pdfork_args), (sy_call_t *)sys_pdfork, AUE_PDFORK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 518 = pdfork */ @@ -594,13 +594,12 @@ struct sysent freebsd32_sysent[] = { { AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */ { AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */ { AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */ - { AS(freebsd32_cap_rights_limit_args), (sy_call_t *)freebsd32_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 533 = freebsd32_cap_rights_limit */ #else { AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */ { AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */ { AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */ - { AS(freebsd32_cap_rights_limit_args), (sy_call_t *)freebsd32_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 533 = freebsd32_cap_rights_limit */ #endif + { AS(cap_rights_limit_args), (sy_call_t *)sys_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 533 = cap_rights_limit */ { AS(freebsd32_cap_ioctls_limit_args), (sy_call_t *)freebsd32_cap_ioctls_limit, AUE_CAP_IOCTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 534 = freebsd32_cap_ioctls_limit */ { AS(freebsd32_cap_ioctls_get_args), (sy_call_t *)freebsd32_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = freebsd32_cap_ioctls_get */ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */ diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index 94ff863..7146ee4 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -2990,20 +2990,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 2; break; } - /* cap_new */ - case 514: { - struct cap_new_args *p = params; - iarg[0] = p->fd; /* int */ - uarg[1] = p->rights; /* uint64_t */ - *n_args = 2; - break; - } - /* cap_rights_get */ + /* __cap_rights_get */ case 515: { - struct cap_rights_get_args *p = params; - iarg[0] = p->fd; /* int */ - uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */ - *n_args = 2; + struct __cap_rights_get_args *p = params; + iarg[0] = p->version; /* int */ + iarg[1] = p->fd; /* int */ + uarg[2] = (intptr_t) p->rightsp; /* cap_rights_t * */ + *n_args = 3; break; } /* cap_enter */ @@ -3159,16 +3152,6 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 8; break; } - /* freebsd32_cap_rights_limit */ - case 533: { - struct freebsd32_cap_rights_limit_args *p = params; - iarg[0] = p->fd; /* int */ - iarg[1] = p->pad; /* int */ - uarg[2] = p->rights1; /* uint32_t */ - uarg[3] = p->rights2; /* uint32_t */ - *n_args = 4; - break; - } #else /* freebsd32_posix_fallocate */ case 530: { @@ -3206,16 +3189,15 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 7; break; } - /* freebsd32_cap_rights_limit */ +#endif + /* cap_rights_limit */ case 533: { - struct freebsd32_cap_rights_limit_args *p = params; + struct cap_rights_limit_args *p = params; iarg[0] = p->fd; /* int */ - uarg[1] = p->rights1; /* uint32_t */ - uarg[2] = p->rights2; /* uint32_t */ - *n_args = 3; + uarg[1] = (intptr_t) p->rightsp; /* cap_rights_t * */ + *n_args = 2; break; } -#endif /* freebsd32_cap_ioctls_limit */ case 534: { struct freebsd32_cap_ioctls_limit_args *p = params; @@ -8277,27 +8259,17 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; - /* cap_new */ - case 514: + /* __cap_rights_get */ + case 515: switch(ndx) { case 0: p = "int"; break; case 1: - p = "uint64_t"; - break; - default: - break; - }; - break; - /* cap_rights_get */ - case 515: - switch(ndx) { - case 0: p = "int"; break; - case 1: - p = "uint64_t *"; + case 2: + p = "cap_rights_t *"; break; default: break; @@ -8583,25 +8555,6 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; - /* freebsd32_cap_rights_limit */ - case 533: - switch(ndx) { - case 0: - p = "int"; - break; - case 1: - p = "int"; - break; - case 2: - p = "uint32_t"; - break; - case 3: - p = "uint32_t"; - break; - default: - break; - }; - break; #else /* freebsd32_posix_fallocate */ case 530: @@ -8678,23 +8631,20 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; - /* freebsd32_cap_rights_limit */ +#endif + /* cap_rights_limit */ case 533: switch(ndx) { case 0: p = "int"; break; case 1: - p = "uint32_t"; - break; - case 2: - p = "uint32_t"; + p = "cap_rights_t *"; break; default: break; }; break; -#endif /* freebsd32_cap_ioctls_limit */ case 534: switch(ndx) { @@ -10567,12 +10517,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; - /* cap_new */ - case 514: - if (ndx == 0 || ndx == 1) - p = "int"; - break; - /* cap_rights_get */ + /* __cap_rights_get */ case 515: if (ndx == 0 || ndx == 1) p = "int"; @@ -10655,11 +10600,6 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; - /* freebsd32_cap_rights_limit */ - case 533: - if (ndx == 0 || ndx == 1) - p = "int"; - break; #else /* freebsd32_posix_fallocate */ case 530: @@ -10676,12 +10616,12 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; - /* freebsd32_cap_rights_limit */ +#endif + /* cap_rights_limit */ case 533: if (ndx == 0 || ndx == 1) p = "int"; break; -#endif /* freebsd32_cap_ioctls_limit */ case 534: if (ndx == 0 || ndx == 1) diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index a2e3e78..f537a54 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -970,9 +970,9 @@ 512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \ struct shmid_ds32 *buf); } 513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); } -514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, uint64_t rights); } -515 AUE_CAP_RIGHTS_GET NOPROTO { int cap_rights_get(int fd, \ - uint64_t *rightsp); } +514 AUE_NULL OBSOL cap_new +515 AUE_CAP_RIGHTS_GET NOPROTO { int __cap_rights_get(int version, \ + int fd, cap_rights_t *rightsp); } 516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); } 517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); } 518 AUE_PDFORK NOPROTO { int pdfork(int *fdp, int flags); } @@ -1016,10 +1016,6 @@ int *status, int options, \ struct wrusage32 *wrusage, \ siginfo_t *info); } -533 AUE_CAP_RIGHTS_LIMIT STD { \ - int freebsd32_cap_rights_limit(int fd, \ - int pad, \ - uint32_t rights1, uint32_t rights2); } #else 530 AUE_NULL STD { int freebsd32_posix_fallocate(int fd,\ uint32_t offset1, uint32_t offset2,\ @@ -1033,10 +1029,10 @@ int *status, int options, \ struct wrusage32 *wrusage, \ siginfo_t *info); } -533 AUE_CAP_RIGHTS_LIMIT STD { \ - int freebsd32_cap_rights_limit(int fd, \ - uint32_t rights1, uint32_t rights2); } #endif +533 AUE_CAP_RIGHTS_LIMIT NOPROTO { \ + int cap_rights_limit(int fd, \ + cap_rights_t *rightsp); } 534 AUE_CAP_IOCTLS_LIMIT STD { \ int freebsd32_cap_ioctls_limit(int fd, \ const uint32_t *cmds, size_t ncmds); } diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 49c3fdf..a6b1d35 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -92,6 +92,7 @@ linux_creat(struct thread *td, struct linux_creat_args *args) static int linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode) { + cap_rights_t rights; struct proc *p = td->td_proc; struct file *fp; int fd; @@ -143,7 +144,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod * having the same filedesc could use that fd without * checking below. */ - error = fget(td, fd, CAP_IOCTL, &fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (!error) { sx_slock(&proctree_lock); PROC_LOCK(p); @@ -328,6 +329,7 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args, caddr_t outp; /* Linux-format */ int resid, linuxreclen=0; /* Linux-format */ caddr_t lbuf; /* Linux-format */ + cap_rights_t rights; struct file *fp; struct uio auio; struct iovec aiov; @@ -348,7 +350,9 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args, } else justone = 0; - if ((error = getvnode(td->td_proc->p_fd, args->fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, args->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -1024,6 +1028,7 @@ linux_pread(td, uap) struct linux_pread_args *uap; { struct pread_args bsd; + cap_rights_t rights; struct vnode *vp; int error; @@ -1036,7 +1041,9 @@ linux_pread(td, uap) if (error == 0) { /* This seems to violate POSIX but linux does it */ - if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0) + error = fgetvp(td, uap->fd, + cap_rights_init(&rights, CAP_PREAD), &vp); + if (error != 0) return (error); if (vp->v_type == VDIR) { vrele(vp); @@ -1283,6 +1290,7 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args) { struct l_flock linux_flock; struct flock bsd_flock; + cap_rights_t rights; struct file *fp; long arg; int error, result; @@ -1385,7 +1393,8 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args) * significant effect for pipes (SIGIO is not delivered for * pipes under Linux-2.2.35 at least). */ - error = fget(td, args->fd, CAP_FCNTL, &fp); + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_FCNTL), &fp); if (error) return (error); if (fp->f_type == DTYPE_PIPE) { diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 4df28aa..2a4016a 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -189,12 +189,14 @@ struct linux_hd_big_geometry { static int linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; u_int sectorsize, fwcylinders, fwheads, fwsectors; off_t mediasize, bytespercyl; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); switch (args->cmd & 0xffff) { case LINUX_HDIO_GET_GEO: @@ -270,12 +272,14 @@ linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; u_int sectorsize; off_t mediasize; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); switch (args->cmd & 0xffff) { case LINUX_BLKGETSIZE: @@ -698,10 +702,12 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) struct termios bios; struct linux_termios lios; struct linux_termio lio; + cap_rights_t rights; struct file *fp; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -1438,10 +1444,12 @@ bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp) static int linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -1963,10 +1971,12 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -2351,6 +2361,7 @@ static int linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) { char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; + cap_rights_t rights; struct ifnet *ifp; struct file *fp; int error, type; @@ -2358,7 +2369,8 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) ifp = NULL; error = 0; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); type = fp->f_type; fdrop(fp, td); @@ -2581,10 +2593,12 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error, type; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); type = fp->f_type; fdrop(fp, td); @@ -2606,11 +2620,13 @@ linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; u_long cmd; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) { + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) { printf("sg_linux_ioctl: fget returned %d\n", error); return (error); } @@ -2828,6 +2844,7 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) static int linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; struct video_tuner vtun; @@ -2845,7 +2862,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break; case LINUX_VIDIOCGTUNER: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); if (error) { @@ -2863,7 +2882,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); case LINUX_VIDIOCSTUNER: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); if (error) { @@ -2880,7 +2901,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break; case LINUX_VIDIOCGWIN: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td); if (!error) { @@ -2892,7 +2915,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); case LINUX_VIDIOCSWIN: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin)); if (error) { @@ -2915,7 +2940,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); case LINUX_VIDIOCGFBUF: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td); if (!error) { @@ -2927,7 +2954,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); case LINUX_VIDIOCSFBUF: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf)); if (error) { @@ -2955,7 +2984,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break; case LINUX_VIDIOCSMICROCODE: - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode)); if (error) { @@ -3108,6 +3139,7 @@ bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf) static int linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; struct v4l2_format vformat; @@ -3199,7 +3231,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat)); if (error) return (error); - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error) return (error); if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0) error = EINVAL; @@ -3222,7 +3256,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) if (error) return (error); linux_to_bsd_v4l2_standard(&l_vstd, &vstd); - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error) return (error); error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd, td->td_ucred, td); @@ -3244,7 +3280,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) sizeof(struct l_v4l2_input)); if (error != 0) return (error); - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp, td->td_ucred, td); @@ -3263,7 +3301,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf)); if (error) return (error); - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, + cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error) return (error); linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf); if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF) @@ -3432,6 +3472,7 @@ linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args) int linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; struct handler_element *he; int error, cmd; @@ -3442,7 +3483,8 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args) (unsigned long)args->cmd); #endif - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); if ((fp->f_flag & (FREAD|FWRITE)) == 0) { fdrop(fp, td); diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 36b23ac..22f811c 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -748,6 +748,7 @@ int linux_connect(struct thread *, struct linux_connect_args *); int linux_connect(struct thread *td, struct linux_connect_args *args) { + cap_rights_t rights; struct socket *so; struct sockaddr *sa; u_int fflag; @@ -772,7 +773,8 @@ linux_connect(struct thread *td, struct linux_connect_args *args) * socket and use the file descriptor reference instead of * creating a new one. */ - error = fgetsock(td, args->s, CAP_CONNECT, &so, &fflag); + error = fgetsock(td, args->s, cap_rights_init(&rights, CAP_CONNECT), + &so, &fflag); if (error == 0) { error = EISCONN; if (fflag & FNONBLOCK) { diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c index 86fab78..8d0b715 100644 --- a/sys/compat/svr4/svr4_fcntl.c +++ b/sys/compat/svr4/svr4_fcntl.c @@ -259,6 +259,7 @@ fd_revoke(td, fd) struct vnode *vp; struct mount *mp; struct vattr vattr; + cap_rights_t rights; int error, *retval; retval = td->td_retval; @@ -267,12 +268,13 @@ fd_revoke(td, fd) * or FreeBSD grows a native frevoke() (more likely), we will need a * CAP_FREVOKE here. * - * In the meantime, use CAP_ALL: if a SVR4 process wants to + * In the meantime, use CAP_ALL(): if a SVR4 process wants to * do an frevoke(), it needs to do it on either a regular file * descriptor or a fully-privileged capability (which is effectively * the same as a non-capability-restricted file descriptor). */ - if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0) + CAP_ALL(&rights); + if ((error = fgetvp(td, fd, &rights, &vp)) != 0) return (error); if (vp->v_type != VCHR && vp->v_type != VBLK) { @@ -318,13 +320,15 @@ fd_truncate(td, fd, flp) struct vattr vattr; int error, *retval; struct ftruncate_args ft; + cap_rights_t rights; retval = td->td_retval; /* * We only support truncating the file. */ - if ((error = fget(td, fd, CAP_FTRUNCATE, &fp)) != 0) + error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp); + if (error != 0) return (error); vp = fp->f_vnode; @@ -401,9 +405,11 @@ svr4_sys_open(td, uap) if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { #if defined(NOTYET) - struct file *fp; + cap_rights_t rights; + struct file *fp; - error = fget(td, retval, CAP_IOCTL, &fp); + error = fget(td, retval, + cap_rights_init(&rights, CAP_IOCTL), &fp); PROC_UNLOCK(p); /* * we may have lost a race the above open() and diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c index 0fbba07..b953e72 100644 --- a/sys/compat/svr4/svr4_filio.c +++ b/sys/compat/svr4/svr4_filio.c @@ -104,6 +104,7 @@ svr4_sys_read(td, uap) struct svr4_sys_read_args *uap; { struct read_args ra; + cap_rights_t rights; struct file *fp; struct socket *so = NULL; int so_state; @@ -114,7 +115,7 @@ svr4_sys_read(td, uap) ra.buf = uap->buf; ra.nbyte = uap->nbyte; - if (fget(td, uap->fd, CAP_READ, &fp) != 0) { + if (fget(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp) != 0) { DPRINTF(("Something fishy with the user-supplied file descriptor...\n")); return EBADF; } diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c index 36b0580..a8c8c8c 100644 --- a/sys/compat/svr4/svr4_ioctl.c +++ b/sys/compat/svr4/svr4_ioctl.c @@ -84,6 +84,7 @@ svr4_sys_ioctl(td, uap) struct svr4_sys_ioctl_args *uap; { int *retval; + cap_rights_t rights; struct file *fp; u_long cmd; int (*fun)(struct file *, struct thread *, register_t *, @@ -103,7 +104,8 @@ svr4_sys_ioctl(td, uap) retval = td->td_retval; cmd = uap->com; - if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 0cfaeae..4888698 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -236,6 +236,7 @@ svr4_sys_getdents64(td, uap) int len, reclen; /* BSD-format */ caddr_t outp; /* SVR4-format */ int resid, svr4reclen=0; /* SVR4-format */ + cap_rights_t rights; struct file *fp; struct uio auio; struct iovec aiov; @@ -247,7 +248,9 @@ svr4_sys_getdents64(td, uap) DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n", uap->fd, uap->nbytes)); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -412,6 +415,7 @@ svr4_sys_getdents(td, uap) int len, reclen; /* BSD-format */ caddr_t outp; /* SVR4-format */ int resid, svr4_reclen; /* SVR4-format */ + cap_rights_t rights; struct file *fp; struct uio auio; struct iovec aiov; @@ -424,7 +428,9 @@ svr4_sys_getdents(td, uap) if (uap->nbytes < 0) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c index 1c7e83e..6348b9b 100644 --- a/sys/compat/svr4/svr4_stream.c +++ b/sys/compat/svr4/svr4_stream.c @@ -1446,10 +1446,12 @@ svr4_sys_putmsg(td, uap) struct thread *td; struct svr4_sys_putmsg_args *uap; { - struct file *fp; + cap_rights_t rights; + struct file *fp; int error; - if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) { + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEND), &fp); + if (error != 0) { #ifdef DEBUG_SVR4 uprintf("putmsg: bad fp\n"); #endif @@ -1618,10 +1620,12 @@ svr4_sys_getmsg(td, uap) struct thread *td; struct svr4_sys_getmsg_args *uap; { - struct file *fp; + cap_rights_t rights; + struct file *fp; int error; - if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) { + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_RECV), &fp); + if (error != 0) { #ifdef DEBUG_SVR4 uprintf("getmsg: bad fp\n"); #endif diff --git a/sys/conf/files b/sys/conf/files index 9480771..2920581 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2848,6 +2848,7 @@ kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_bus_dma.c standard kern/subr_bufring.c standard +kern/subr_capability.c standard kern/subr_clock.c standard kern/subr_counter.c standard kern/subr_devstat.c standard diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 6d35d1f..1a66aa5 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -138,10 +138,13 @@ amd64/amd64/uma_machdep.c standard amd64/amd64/vm_machdep.c standard amd64/pci/pci_cfgreg.c optional pci cddl/contrib/opensolaris/common/atomic/amd64/opensolaris_atomic.S optional zfs compile-with "${ZFS_S}" -crypto/aesni/aesencdec_amd64.S optional aesni crypto/aesni/aeskeys_amd64.S optional aesni crypto/aesni/aesni.c optional aesni -crypto/aesni/aesni_wrap.c optional aesni +aesni_wrap.o optional aesni \ + dependency "$S/crypto/aesni/aesni_wrap.c" \ + compile-with "${CC} -c ${CFLAGS:C/^-O2$/-O3/:N-nostdinc} ${WERROR} ${PROF} -mmmx -msse -maes ${.IMPSRC}" \ + no-implicit-rule \ + clean "aesni_wrap.o" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb crypto/via/padlock.c optional padlock diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 2ac0b61..24dac5f 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -124,10 +124,13 @@ bf_enc.o optional crypto | ipsec \ dependency "$S/crypto/blowfish/arch/i386/bf_enc.S $S/crypto/blowfish/arch/i386/bf_enc_586.S $S/crypto/blowfish/arch/i386/bf_enc_686.S" \ compile-with "${CC} -c -I$S/crypto/blowfish/arch/i386 ${ASM_CFLAGS} ${WERROR} ${.IMPSRC}" \ no-implicit-rule -crypto/aesni/aesencdec_i386.S optional aesni crypto/aesni/aeskeys_i386.S optional aesni crypto/aesni/aesni.c optional aesni -crypto/aesni/aesni_wrap.c optional aesni +aesni_wrap.o optional aesni \ + dependency "$S/crypto/aesni/aesni_wrap.c" \ + compile-with "${CC} -c ${CFLAGS:C/^-O2$/-O3/:N-nostdinc} ${WERROR} ${PROF} -mmmx -msse -maes ${.IMPSRC}" \ + no-implicit-rule \ + clean "aesni_wrap.o" crypto/des/arch/i386/des_enc.S optional crypto | ipsec | netsmb crypto/via/padlock.c optional padlock crypto/via/padlock_cipher.c optional padlock diff --git a/sys/conf/files.mips b/sys/conf/files.mips index ca8dee2..7f54f08 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -56,6 +56,7 @@ libkern/ffsl.c standard libkern/fls.c standard libkern/flsl.c standard libkern/memmove.c standard +libkern/cmpdi2.c optional mips | mipsel libkern/ucmpdi2.c optional mips | mipsel # cfe support diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 5808d85..fc0663e 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -30,6 +30,7 @@ dev/agp/agp_apple.c optional agp powermac dev/fb/fb.c optional sc dev/fdt/fdt_powerpc.c optional fdt dev/hwpmc/hwpmc_powerpc.c optional hwpmc +dev/hwpmc/hwpmc_mpc7xxx.c optional hwpmc dev/iicbus/ad7417.c optional ad7417 powermac dev/iicbus/ds1631.c optional ds1631 powermac dev/iicbus/ds1775.c optional ds1775 powermac diff --git a/sys/crypto/aesni/aesencdec.h b/sys/crypto/aesni/aesencdec.h new file mode 100644 index 0000000..0c9bf5f --- /dev/null +++ b/sys/crypto/aesni/aesencdec.h @@ -0,0 +1,136 @@ +/*- + * Copyright 2013 John-Mark Gurney <jmg@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#include <wmmintrin.h> + +static inline void +aesni_enc8(int rounds, const uint8_t *key_schedule, __m128i a, + __m128i b, __m128i c, __m128i d, __m128i e, __m128i f, __m128i g, + __m128i h, __m128i out[8]) +{ + const __m128i *keysched = (const __m128i *)key_schedule; + int i; + + a ^= keysched[0]; + b ^= keysched[0]; + c ^= keysched[0]; + d ^= keysched[0]; + e ^= keysched[0]; + f ^= keysched[0]; + g ^= keysched[0]; + h ^= keysched[0]; + + for (i = 0; i < rounds; i++) { + a = _mm_aesenc_si128(a, keysched[i + 1]); + b = _mm_aesenc_si128(b, keysched[i + 1]); + c = _mm_aesenc_si128(c, keysched[i + 1]); + d = _mm_aesenc_si128(d, keysched[i + 1]); + e = _mm_aesenc_si128(e, keysched[i + 1]); + f = _mm_aesenc_si128(f, keysched[i + 1]); + g = _mm_aesenc_si128(g, keysched[i + 1]); + h = _mm_aesenc_si128(h, keysched[i + 1]); + } + + out[0] = _mm_aesenclast_si128(a, keysched[i + 1]); + out[1] = _mm_aesenclast_si128(b, keysched[i + 1]); + out[2] = _mm_aesenclast_si128(c, keysched[i + 1]); + out[3] = _mm_aesenclast_si128(d, keysched[i + 1]); + out[4] = _mm_aesenclast_si128(e, keysched[i + 1]); + out[5] = _mm_aesenclast_si128(f, keysched[i + 1]); + out[6] = _mm_aesenclast_si128(g, keysched[i + 1]); + out[7] = _mm_aesenclast_si128(h, keysched[i + 1]); +} + +static inline void +aesni_dec8(int rounds, const uint8_t *key_schedule, __m128i a, + __m128i b, __m128i c, __m128i d, __m128i e, __m128i f, __m128i g, + __m128i h, __m128i out[8]) +{ + const __m128i *keysched = (const __m128i *)key_schedule; + int i; + + a ^= keysched[0]; + b ^= keysched[0]; + c ^= keysched[0]; + d ^= keysched[0]; + e ^= keysched[0]; + f ^= keysched[0]; + g ^= keysched[0]; + h ^= keysched[0]; + + for (i = 0; i < rounds; i++) { + a = _mm_aesdec_si128(a, keysched[i + 1]); + b = _mm_aesdec_si128(b, keysched[i + 1]); + c = _mm_aesdec_si128(c, keysched[i + 1]); + d = _mm_aesdec_si128(d, keysched[i + 1]); + e = _mm_aesdec_si128(e, keysched[i + 1]); + f = _mm_aesdec_si128(f, keysched[i + 1]); + g = _mm_aesdec_si128(g, keysched[i + 1]); + h = _mm_aesdec_si128(h, keysched[i + 1]); + } + + out[0] = _mm_aesdeclast_si128(a, keysched[i + 1]); + out[1] = _mm_aesdeclast_si128(b, keysched[i + 1]); + out[2] = _mm_aesdeclast_si128(c, keysched[i + 1]); + out[3] = _mm_aesdeclast_si128(d, keysched[i + 1]); + out[4] = _mm_aesdeclast_si128(e, keysched[i + 1]); + out[5] = _mm_aesdeclast_si128(f, keysched[i + 1]); + out[6] = _mm_aesdeclast_si128(g, keysched[i + 1]); + out[7] = _mm_aesdeclast_si128(h, keysched[i + 1]); +} + +static inline __m128i +aesni_enc(int rounds, const uint8_t *key_schedule, const __m128i from) +{ + __m128i tmp; + const __m128i *keysched = (const __m128i *)key_schedule; + int i; + + tmp = from ^ keysched[0]; + + for (i = 0; i < rounds; i++) + tmp = _mm_aesenc_si128(tmp, keysched[i + 1]); + + return _mm_aesenclast_si128(tmp, keysched[i + 1]); +} + +static inline __m128i +aesni_dec(int rounds, const uint8_t *key_schedule, const __m128i from) +{ + __m128i tmp; + const __m128i *keysched = (const __m128i *)key_schedule; + int i; + + tmp = from ^ keysched[0]; + + for (i = 0; i < rounds; i++) + tmp = _mm_aesdec_si128(tmp, keysched[i + 1]); + + return _mm_aesdeclast_si128(tmp, keysched[i + 1]); +} diff --git a/sys/crypto/aesni/aesencdec_amd64.S b/sys/crypto/aesni/aesencdec_amd64.S deleted file mode 100644 index f77918b..0000000 --- a/sys/crypto/aesni/aesencdec_amd64.S +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * Copyright (c) 2010 Konstantin Belousov <kib@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <machine/asmacros.h> - - .text - -ENTRY(aesni_enc) - .cfi_startproc - movdqu (%rdx),%xmm0 - cmpq $0,%r8 - je 1f - movdqu (%r8),%xmm1 /* unaligned load into reg */ - pxor %xmm1,%xmm0 /* pxor otherwise can fault on iv */ -1: - pxor (%rsi),%xmm0 -2: - addq $0x10,%rsi -// aesenc (%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdc,0x06 - decl %edi - jne 2b - addq $0x10,%rsi -// aesenclast (%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdd,0x06 - movdqu %xmm0,(%rcx) - retq - .cfi_endproc -END(aesni_enc) - -ENTRY(aesni_dec) - .cfi_startproc - movdqu (%rdx),%xmm0 - pxor (%rsi),%xmm0 -1: - addq $0x10,%rsi -// aesdec (%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x06 - decl %edi - jne 1b - addq $0x10,%rsi -// aesdeclast (%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x06 - cmpq $0,%r8 - je 2f - movdqu (%r8),%xmm1 - pxor %xmm1,%xmm0 -2: - movdqu %xmm0,(%rcx) - retq - .cfi_endproc -END(aesni_dec) - -ENTRY(aesni_decrypt_cbc) - .cfi_startproc - shrq $4,%rdx - movdqu (%r8),%xmm1 -1: - movdqu (%rcx),%xmm0 - movdqa %xmm0,%xmm2 - pxor (%rsi),%xmm0 - cmpl $12,%edi -// aesdec 0x10(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x10 -// aesdec 0x20(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x20 -// aesdec 0x30(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x30 -// aesdec 0x40(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x40 -// aesdec 0x50(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x50 -// aesdec 0x60(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x60 -// aesdec 0x70(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x46,0x70 -// aesdec 0x80(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0x80,0x00,0x00,0x00 -// aesdec 0x90(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0x90,0x00,0x00,0x00 - jge 2f -// aesdeclast 0xa0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x86,0xa0,0x00,0x00,0x00 - jmp 4f -2: -// aesdec 0xa0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0xa0,0x00,0x00,0x00 -// aesdec 0xb0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0xb0,0x00,0x00,0x00 - jg 3f -// aesdeclast 0xc0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x86,0xc0,0x00,0x00,0x00 - jmp 4f -3: -// aesdec 0xc0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0xc0,0x00,0x00,0x00 -// aesdec 0xd0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x86,0xd0,0x00,0x00,0x00 -// aesdeclast 0xe0(%rsi),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x86,0xe0,0x00,0x00,0x00 -4: - pxor %xmm1,%xmm0 - movdqu %xmm0,(%rcx) - movdqa %xmm2,%xmm1 // iv - addq $0x10,%rcx - decq %rdx - jne 1b - retq - .cfi_endproc -END(aesni_decrypt_cbc) - - .ident "$FreeBSD$" diff --git a/sys/crypto/aesni/aesencdec_i386.S b/sys/crypto/aesni/aesencdec_i386.S deleted file mode 100644 index 78de311..0000000 --- a/sys/crypto/aesni/aesencdec_i386.S +++ /dev/null @@ -1,166 +0,0 @@ -/*- - * Copyright (c) 2010 Konstantin Belousov <kib@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <machine/asmacros.h> - -ENTRY(aesni_enc) - .cfi_startproc - pushl %ebp - .cfi_adjust_cfa_offset 4 - movl %esp,%ebp - movl 8(%ebp),%ecx /* rounds */ - movl 16(%ebp),%edx - movdqu (%edx),%xmm0 /* from */ - movl 24(%ebp),%eax /* iv */ - cmpl $0,%eax - je 1f - movdqu (%eax),%xmm1 - pxor %xmm1,%xmm0 -1: - movl 12(%ebp),%eax /* key */ - pxor (%eax),%xmm0 -2: - addl $0x10,%eax -// aesenc (%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdc,0x00 - loopne 2b - addl $0x10,%eax -// aesenclast (%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdd,0x00 - movl 20(%ebp),%eax - movdqu %xmm0,(%eax) /* to */ - leave - .cfi_adjust_cfa_offset -4 - retl - .cfi_endproc -END(aesni_enc) - -ENTRY(aesni_dec) - .cfi_startproc - pushl %ebp - .cfi_adjust_cfa_offset 4 - movl %esp,%ebp - movl 8(%ebp),%ecx /* rounds */ - movl 16(%ebp),%edx - movdqu (%edx),%xmm0 /* from */ - movl 12(%ebp),%eax /* key */ - pxor (%eax),%xmm0 -1: - addl $0x10,%eax -// aesdec (%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x00 - loopne 1b - addl $0x10,%eax -// aesdeclast (%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x00 - movl 24(%ebp),%eax - cmpl $0,%eax /* iv */ - je 2f - movdqu (%eax),%xmm1 - pxor %xmm1,%xmm0 -2: - movl 20(%ebp),%eax - movdqu %xmm0,(%eax) /* to */ - leave - .cfi_adjust_cfa_offset -4 - retl - .cfi_endproc -END(aesni_dec) - -ENTRY(aesni_decrypt_cbc) - .cfi_startproc - pushl %ebp - .cfi_adjust_cfa_offset 4 - movl %esp,%ebp - pushl %ebx - pushl %esi - movl 12(%ebp),%eax /* key */ - movl 16(%ebp),%ecx /* length */ - shrl $4,%ecx - movl 20(%ebp),%ebx /* buf */ - movl 24(%ebp),%esi - movdqu (%esi),%xmm1 /* iv */ - movl 8(%ebp),%esi /* rounds */ -1: - movdqu (%ebx),%xmm0 - movdqa %xmm0,%xmm2 - pxor (%eax),%xmm0 - cmpl $12,%esi -// aesdec 0x10(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x10 -// aesdec 0x20(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x20 -// aesdec 0x30(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x30 -// aesdec 0x40(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x40 -// aesdec 0x50(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x50 -// aesdec 0x60(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x60 -// aesdec 0x70(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x40,0x70 -// aesdec 0x80(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0x80,0x00,0x00,0x00 -// aesdec 0x90(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0x90,0x00,0x00,0x00 - jge 2f -// aesdeclast 0xa0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x80,0xa0,0x00,0x00,0x00 - jmp 4f -2: -// aesdec 0xa0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0xa0,0x00,0x00,0x00 -// aesdec 0xb0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0xb0,0x00,0x00,0x00 - jg 3f -// aesdeclast 0xc0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x80,0xc0,0x00,0x00,0x00 - jmp 4f -3: -// aesdec 0xc0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0xc0,0x00,0x00,0x00 -// aesdec 0xd0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xde,0x80,0xd0,0x00,0x00,0x00 -// aesdeclast 0xe0(%eax),%xmm0 - .byte 0x66,0x0f,0x38,0xdf,0x80,0xe0,0x00,0x00,0x00 -4: - pxor %xmm1,%xmm0 - movdqu %xmm0,(%ebx) - movdqa %xmm2,%xmm1 - addl $0x10,%ebx - decl %ecx - jne 1b - - popl %esi - popl %ebx - leave - .cfi_adjust_cfa_offset -4 - retl - .cfi_endproc -END(aesni_decrypt_cbc) - - .ident "$FreeBSD$" diff --git a/sys/crypto/aesni/aeskeys_amd64.S b/sys/crypto/aesni/aeskeys_amd64.S index 23a4d3d..9b3e98c 100644 --- a/sys/crypto/aesni/aeskeys_amd64.S +++ b/sys/crypto/aesni/aeskeys_amd64.S @@ -125,103 +125,72 @@ ENTRY(aesni_set_enckey) movups 0x10(%rdi),%xmm2 # other user key movaps %xmm2,(%rsi) addq $0x10,%rsi -// aeskeygenassist $0x1,%xmm2,%xmm1 # round 1 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x01 + aeskeygenassist $0x1,%xmm2,%xmm1 # round 1 call _key_expansion_256a -// aeskeygenassist $0x1,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x01 + aeskeygenassist $0x1,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x2,%xmm2,%xmm1 # round 2 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x02 + aeskeygenassist $0x2,%xmm2,%xmm1 # round 2 call _key_expansion_256a -// aeskeygenassist $0x2,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x02 + aeskeygenassist $0x2,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x4,%xmm2,%xmm1 # round 3 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x04 + aeskeygenassist $0x4,%xmm2,%xmm1 # round 3 call _key_expansion_256a -// aeskeygenassist $0x4,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x04 + aeskeygenassist $0x4,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x8,%xmm2,%xmm1 # round 4 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x08 + aeskeygenassist $0x8,%xmm2,%xmm1 # round 4 call _key_expansion_256a -// aeskeygenassist $0x8,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x08 + aeskeygenassist $0x8,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x10,%xmm2,%xmm1 # round 5 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x10 + aeskeygenassist $0x10,%xmm2,%xmm1 # round 5 call _key_expansion_256a -// aeskeygenassist $0x10,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x10 + aeskeygenassist $0x10,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x20,%xmm2,%xmm1 # round 6 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x20 + aeskeygenassist $0x20,%xmm2,%xmm1 # round 6 call _key_expansion_256a -// aeskeygenassist $0x20,%xmm0,%xmm1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x20 + aeskeygenassist $0x20,%xmm0,%xmm1 call _key_expansion_256b -// aeskeygenassist $0x40,%xmm2,%xmm1 # round 7 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x40 + aeskeygenassist $0x40,%xmm2,%xmm1 # round 7 call _key_expansion_256a retq .Lenc_key192: movq 0x10(%rdi),%xmm2 # other user key -// aeskeygenassist $0x1,%xmm2,%xmm1 # round 1 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x01 + aeskeygenassist $0x1,%xmm2,%xmm1 # round 1 call _key_expansion_192a -// aeskeygenassist $0x2,%xmm2,%xmm1 # round 2 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x02 + aeskeygenassist $0x2,%xmm2,%xmm1 # round 2 call _key_expansion_192b -// aeskeygenassist $0x4,%xmm2,%xmm1 # round 3 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x04 + aeskeygenassist $0x4,%xmm2,%xmm1 # round 3 call _key_expansion_192a -// aeskeygenassist $0x8,%xmm2,%xmm1 # round 4 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x08 + aeskeygenassist $0x8,%xmm2,%xmm1 # round 4 call _key_expansion_192b -// aeskeygenassist $0x10,%xmm2,%xmm1 # round 5 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x10 + aeskeygenassist $0x10,%xmm2,%xmm1 # round 5 call _key_expansion_192a -// aeskeygenassist $0x20,%xmm2,%xmm1 # round 6 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x20 + aeskeygenassist $0x20,%xmm2,%xmm1 # round 6 call _key_expansion_192b -// aeskeygenassist $0x40,%xmm2,%xmm1 # round 7 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x40 + aeskeygenassist $0x40,%xmm2,%xmm1 # round 7 call _key_expansion_192a -// aeskeygenassist $0x80,%xmm2,%xmm1 # round 8 - .byte 0x66,0x0f,0x3a,0xdf,0xca,0x80 + aeskeygenassist $0x80,%xmm2,%xmm1 # round 8 call _key_expansion_192b retq .Lenc_key128: -// aeskeygenassist $0x1,%xmm0,%xmm1 # round 1 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x01 + aeskeygenassist $0x1,%xmm0,%xmm1 # round 1 call _key_expansion_128 -// aeskeygenassist $0x2,%xmm0,%xmm1 # round 2 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x02 + aeskeygenassist $0x2,%xmm0,%xmm1 # round 2 call _key_expansion_128 -// aeskeygenassist $0x4,%xmm0,%xmm1 # round 3 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x04 + aeskeygenassist $0x4,%xmm0,%xmm1 # round 3 call _key_expansion_128 -// aeskeygenassist $0x8,%xmm0,%xmm1 # round 4 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x08 + aeskeygenassist $0x8,%xmm0,%xmm1 # round 4 call _key_expansion_128 -// aeskeygenassist $0x10,%xmm0,%xmm1 # round 5 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x10 + aeskeygenassist $0x10,%xmm0,%xmm1 # round 5 call _key_expansion_128 -// aeskeygenassist $0x20,%xmm0,%xmm1 # round 6 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x20 + aeskeygenassist $0x20,%xmm0,%xmm1 # round 6 call _key_expansion_128 -// aeskeygenassist $0x40,%xmm0,%xmm1 # round 7 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x40 + aeskeygenassist $0x40,%xmm0,%xmm1 # round 7 call _key_expansion_128 -// aeskeygenassist $0x80,%xmm0,%xmm1 # round 8 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x80 + aeskeygenassist $0x80,%xmm0,%xmm1 # round 8 call _key_expansion_128 -// aeskeygenassist $0x1b,%xmm0,%xmm1 # round 9 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x1b + aeskeygenassist $0x1b,%xmm0,%xmm1 # round 9 call _key_expansion_128 -// aeskeygenassist $0x36,%xmm0,%xmm1 # round 10 - .byte 0x66,0x0f,0x3a,0xdf,0xc8,0x36 + aeskeygenassist $0x36,%xmm0,%xmm1 # round 10 call _key_expansion_128 retq .cfi_endproc @@ -238,8 +207,7 @@ ENTRY(aesni_set_deckey) 1: addq $0x10,%rsi subq $0x10,%rdi -// aesimc (%rdi),%xmm1 - .byte 0x66,0x0f,0x38,0xdb,0x0f + aesimc (%rdi),%xmm1 movdqa %xmm1,(%rsi) decl %edx jne 1b diff --git a/sys/crypto/aesni/aesni.c b/sys/crypto/aesni/aesni.c index ca00a57..73eb28a 100644 --- a/sys/crypto/aesni/aesni.c +++ b/sys/crypto/aesni/aesni.c @@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/uio.h> #include <crypto/aesni/aesni.h> -#include "cryptodev_if.h" +#include <cryptodev_if.h> struct aesni_softc { int32_t cid; @@ -74,6 +74,12 @@ aesni_probe(device_t dev) device_printf(dev, "No AESNI support.\n"); return (EINVAL); } + + if ((cpu_feature & CPUID_SSE2) == 0) { + device_printf(dev, "No SSE2 support but AESNI!?!\n"); + return (EINVAL); + } + device_set_desc_copy(dev, "AES-CBC,AES-XTS"); return (0); } diff --git a/sys/crypto/aesni/aesni.h b/sys/crypto/aesni/aesni.h index 78255b7..17ca9c5 100644 --- a/sys/crypto/aesni/aesni.h +++ b/sys/crypto/aesni/aesni.h @@ -71,12 +71,6 @@ struct aesni_session { /* * Internal functions, implemented in assembler. */ -void aesni_enc(int rounds, const uint8_t *key_schedule, - const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN], - const uint8_t iv[AES_BLOCK_LEN]); -void aesni_dec(int rounds, const uint8_t *key_schedule, - const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN], - const uint8_t iv[AES_BLOCK_LEN]); void aesni_set_enckey(const uint8_t *userkey, uint8_t *encrypt_schedule, int number_of_rounds); void aesni_set_deckey(const uint8_t *encrypt_schedule, @@ -88,12 +82,19 @@ void aesni_set_deckey(const uint8_t *encrypt_schedule, void aesni_encrypt_cbc(int rounds, const void *key_schedule, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN]); void aesni_decrypt_cbc(int rounds, const void *key_schedule, size_t len, - const uint8_t *from, const uint8_t iv[AES_BLOCK_LEN]); + uint8_t *buf, const uint8_t iv[AES_BLOCK_LEN]); void aesni_encrypt_ecb(int rounds, const void *key_schedule, size_t len, const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]); void aesni_decrypt_ecb(int rounds, const void *key_schedule, size_t len, const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]); +void aesni_encrypt_xts(int rounds, const void *data_schedule, + const void *tweak_schedule, size_t len, const uint8_t *from, uint8_t *to, + const uint8_t iv[AES_BLOCK_LEN]); +void aesni_decrypt_xts(int rounds, const void *data_schedule, + const void *tweak_schedule, size_t len, const uint8_t *from, uint8_t *to, + const uint8_t iv[AES_BLOCK_LEN]); + int aesni_cipher_setup(struct aesni_session *ses, struct cryptoini *encini); int aesni_cipher_process(struct aesni_session *ses, diff --git a/sys/crypto/aesni/aesni_wrap.c b/sys/crypto/aesni/aesni_wrap.c index 3340b1f..197baf7 100644 --- a/sys/crypto/aesni/aesni_wrap.c +++ b/sys/crypto/aesni/aesni_wrap.c @@ -2,6 +2,7 @@ * Copyright (C) 2008 Damien Miller <djm@mindrot.org> * Copyright (c) 2010 Konstantin Belousov <kib@FreeBSD.org> * Copyright (c) 2010-2011 Pawel Jakub Dawidek <pawel@dawidek.net> + * Copyright 2012-2013 John-Mark Gurney <jmg@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,13 +29,15 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); - + #include <sys/param.h> #include <sys/libkern.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/systm.h> #include <crypto/aesni/aesni.h> + +#include "aesencdec.h" MALLOC_DECLARE(M_AESNI); @@ -42,28 +45,78 @@ void aesni_encrypt_cbc(int rounds, const void *key_schedule, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN]) { - const uint8_t *ivp; + __m128i tot, ivreg; size_t i; len /= AES_BLOCK_LEN; - ivp = iv; + ivreg = _mm_loadu_si128((const __m128i *)iv); for (i = 0; i < len; i++) { - aesni_enc(rounds - 1, key_schedule, from, to, ivp); - ivp = to; + tot = aesni_enc(rounds - 1, key_schedule, + _mm_loadu_si128((const __m128i *)from) ^ ivreg); + ivreg = tot; + _mm_storeu_si128((__m128i *)to, tot); from += AES_BLOCK_LEN; to += AES_BLOCK_LEN; } } void -aesni_encrypt_ecb(int rounds, const void *key_schedule, size_t len, - const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]) +aesni_decrypt_cbc(int rounds, const void *key_schedule, size_t len, + uint8_t *buf, const uint8_t iv[AES_BLOCK_LEN]) { - size_t i; + __m128i blocks[8]; + __m128i *bufs; + __m128i ivreg, nextiv; + size_t i, j, cnt; + + ivreg = _mm_loadu_si128((const __m128i *)iv); + cnt = len / AES_BLOCK_LEN / 8; + for (i = 0; i < cnt; i++) { + bufs = (__m128i *)buf; + aesni_dec8(rounds - 1, key_schedule, bufs[0], bufs[1], + bufs[2], bufs[3], bufs[4], bufs[5], bufs[6], + bufs[7], &blocks[0]); + for (j = 0; j < 8; j++) { + nextiv = bufs[j]; + bufs[j] = blocks[j] ^ ivreg; + ivreg = nextiv; + } + buf += AES_BLOCK_LEN * 8; + } + i *= 8; + cnt = len / AES_BLOCK_LEN; + for (; i < cnt; i++) { + bufs = (__m128i *)buf; + nextiv = bufs[0]; + bufs[0] = aesni_dec(rounds - 1, key_schedule, bufs[0]) ^ ivreg; + ivreg = nextiv; + buf += AES_BLOCK_LEN; + } +} - len /= AES_BLOCK_LEN; - for (i = 0; i < len; i++) { - aesni_enc(rounds - 1, key_schedule, from, to, NULL); +void +aesni_encrypt_ecb(int rounds, const void *key_schedule, size_t len, + const uint8_t *from, uint8_t *to) +{ + __m128i tot; + const __m128i *blocks; + size_t i, cnt; + + cnt = len / AES_BLOCK_LEN / 8; + for (i = 0; i < cnt; i++) { + blocks = (const __m128i *)from; + aesni_enc8(rounds - 1, key_schedule, blocks[0], blocks[1], + blocks[2], blocks[3], blocks[4], blocks[5], blocks[6], + blocks[7], (__m128i *)to); + from += AES_BLOCK_LEN * 8; + to += AES_BLOCK_LEN * 8; + } + i *= 8; + cnt = len / AES_BLOCK_LEN; + for (; i < cnt; i++) { + tot = aesni_enc(rounds - 1, key_schedule, + _mm_loadu_si128((const __m128i *)from)); + _mm_storeu_si128((__m128i *)to, tot); from += AES_BLOCK_LEN; to += AES_BLOCK_LEN; } @@ -73,11 +126,25 @@ void aesni_decrypt_ecb(int rounds, const void *key_schedule, size_t len, const uint8_t from[AES_BLOCK_LEN], uint8_t to[AES_BLOCK_LEN]) { - size_t i; - - len /= AES_BLOCK_LEN; - for (i = 0; i < len; i++) { - aesni_dec(rounds - 1, key_schedule, from, to, NULL); + __m128i tot; + const __m128i *blocks; + size_t i, cnt; + + cnt = len / AES_BLOCK_LEN / 8; + for (i = 0; i < cnt; i++) { + blocks = (const __m128i *)from; + aesni_dec8(rounds - 1, key_schedule, blocks[0], blocks[1], + blocks[2], blocks[3], blocks[4], blocks[5], blocks[6], + blocks[7], (__m128i *)to); + from += AES_BLOCK_LEN * 8; + to += AES_BLOCK_LEN * 8; + } + i *= 8; + cnt = len / AES_BLOCK_LEN; + for (; i < cnt; i++) { + tot = aesni_dec(rounds - 1, key_schedule, + _mm_loadu_si128((const __m128i *)from)); + _mm_storeu_si128((__m128i *)to, tot); from += AES_BLOCK_LEN; to += AES_BLOCK_LEN; } @@ -87,34 +154,88 @@ aesni_decrypt_ecb(int rounds, const void *key_schedule, size_t len, #define AES_XTS_IVSIZE 8 #define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ +static inline __m128i +xts_crank_lfsr(__m128i inp) +{ + const __m128i alphamask = _mm_set_epi32(1, 1, 1, AES_XTS_ALPHA); + __m128i xtweak, ret; + + /* set up xor mask */ + xtweak = _mm_shuffle_epi32(inp, 0x93); + xtweak = _mm_srai_epi32(xtweak, 31); + xtweak &= alphamask; + + /* next term */ + ret = _mm_slli_epi32(inp, 1); + ret ^= xtweak; + + return ret; +} + static void -aesni_crypt_xts_block(int rounds, const void *key_schedule, uint64_t *tweak, - const uint64_t *from, uint64_t *to, uint64_t *block, int do_encrypt) +aesni_crypt_xts_block(int rounds, const void *key_schedule, __m128i *tweak, + const __m128i *from, __m128i *to, int do_encrypt) { - int carry; + __m128i block; - block[0] = from[0] ^ tweak[0]; - block[1] = from[1] ^ tweak[1]; + block = *from ^ *tweak; if (do_encrypt) - aesni_enc(rounds - 1, key_schedule, (uint8_t *)block, (uint8_t *)to, NULL); + block = aesni_enc(rounds - 1, key_schedule, block); else - aesni_dec(rounds - 1, key_schedule, (uint8_t *)block, (uint8_t *)to, NULL); + block = aesni_dec(rounds - 1, key_schedule, block); - to[0] ^= tweak[0]; - to[1] ^= tweak[1]; + *to = block ^ *tweak; - /* Exponentiate tweak. */ - carry = ((tweak[0] & 0x8000000000000000ULL) > 0); - tweak[0] <<= 1; - if (tweak[1] & 0x8000000000000000ULL) { - uint8_t *twk = (uint8_t *)tweak; + *tweak = xts_crank_lfsr(*tweak); +} - twk[0] ^= AES_XTS_ALPHA; - } - tweak[1] <<= 1; - if (carry) - tweak[1] |= 1; +static void +aesni_crypt_xts_block8(int rounds, const void *key_schedule, __m128i *tweak, + const __m128i *from, __m128i *to, int do_encrypt) +{ + __m128i tmptweak; + __m128i a, b, c, d, e, f, g, h; + __m128i tweaks[8]; + __m128i tmp[8]; + + tmptweak = *tweak; + + /* + * unroll the loop. This lets gcc put values directly in the + * register and saves memory accesses. + */ +#define PREPINP(v, pos) \ + do { \ + tweaks[(pos)] = tmptweak; \ + (v) = from[(pos)] ^ tmptweak; \ + tmptweak = xts_crank_lfsr(tmptweak); \ + } while (0) + PREPINP(a, 0); + PREPINP(b, 1); + PREPINP(c, 2); + PREPINP(d, 3); + PREPINP(e, 4); + PREPINP(f, 5); + PREPINP(g, 6); + PREPINP(h, 7); + *tweak = tmptweak; + + if (do_encrypt) + aesni_enc8(rounds - 1, key_schedule, a, b, c, d, e, f, g, h, + tmp); + else + aesni_dec8(rounds - 1, key_schedule, a, b, c, d, e, f, g, h, + tmp); + + to[0] = tmp[0] ^ tweaks[0]; + to[1] = tmp[1] ^ tweaks[1]; + to[2] = tmp[2] ^ tweaks[2]; + to[3] = tmp[3] ^ tweaks[3]; + to[4] = tmp[4] ^ tweaks[4]; + to[5] = tmp[5] ^ tweaks[5]; + to[6] = tmp[6] ^ tweaks[6]; + to[7] = tmp[7] ^ tweaks[7]; } static void @@ -122,9 +243,9 @@ aesni_crypt_xts(int rounds, const void *data_schedule, const void *tweak_schedule, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN], int do_encrypt) { - uint64_t block[AES_XTS_BLOCKSIZE / 8]; - uint8_t tweak[AES_XTS_BLOCKSIZE]; - size_t i; + __m128i tweakreg; + uint8_t tweak[AES_XTS_BLOCKSIZE] __aligned(16); + size_t i, cnt; /* * Prepare tweak as E_k2(IV). IV is specified as LE representation @@ -137,21 +258,27 @@ aesni_crypt_xts(int rounds, const void *data_schedule, #else #error Only LITTLE_ENDIAN architectures are supported. #endif - aesni_enc(rounds - 1, tweak_schedule, tweak, tweak, NULL); - - len /= AES_XTS_BLOCKSIZE; - for (i = 0; i < len; i++) { - aesni_crypt_xts_block(rounds, data_schedule, (uint64_t *)tweak, - (const uint64_t *)from, (uint64_t *)to, block, do_encrypt); + tweakreg = _mm_loadu_si128((__m128i *)&tweak[0]); + tweakreg = aesni_enc(rounds - 1, tweak_schedule, tweakreg); + + cnt = len / AES_XTS_BLOCKSIZE / 8; + for (i = 0; i < cnt; i++) { + aesni_crypt_xts_block8(rounds, data_schedule, &tweakreg, + (const __m128i *)from, (__m128i *)to, do_encrypt); + from += AES_XTS_BLOCKSIZE * 8; + to += AES_XTS_BLOCKSIZE * 8; + } + i *= 8; + cnt = len / AES_XTS_BLOCKSIZE; + for (; i < cnt; i++) { + aesni_crypt_xts_block(rounds, data_schedule, &tweakreg, + (const __m128i *)from, (__m128i *)to, do_encrypt); from += AES_XTS_BLOCKSIZE; to += AES_XTS_BLOCKSIZE; } - - bzero(tweak, sizeof(tweak)); - bzero(block, sizeof(block)); } -static void +void aesni_encrypt_xts(int rounds, const void *data_schedule, const void *tweak_schedule, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN]) @@ -161,7 +288,7 @@ aesni_encrypt_xts(int rounds, const void *data_schedule, iv, 1); } -static void +void aesni_decrypt_xts(int rounds, const void *data_schedule, const void *tweak_schedule, size_t len, const uint8_t *from, uint8_t *to, const uint8_t iv[AES_BLOCK_LEN]) diff --git a/sys/dev/aac/aac_linux.c b/sys/dev/aac/aac_linux.c index 049e2be..591dfbb 100644 --- a/sys/dev/aac/aac_linux.c +++ b/sys/dev/aac/aac_linux.c @@ -75,11 +75,13 @@ MODULE_DEPEND(aac_linux, linux, 1, 1, 1); static int aac_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; u_long cmd; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); cmd = args->cmd; diff --git a/sys/dev/aacraid/aacraid_linux.c b/sys/dev/aacraid/aacraid_linux.c index 3d85445..e58d0a4 100644 --- a/sys/dev/aacraid/aacraid_linux.c +++ b/sys/dev/aacraid/aacraid_linux.c @@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$"); */ #include <sys/param.h> +#if __FreeBSD_version >= 900000 +#include <sys/capability.h> +#endif #include <sys/systm.h> #include <sys/conf.h> #include <sys/kernel.h> @@ -77,15 +80,19 @@ static int aacraid_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { struct file *fp; +#if __FreeBSD_version >= 900000 + cap_rights_t rights; +#endif u_long cmd; int error; + if ((error = fget(td, args->fd, #if __FreeBSD_version >= 900000 - if ((error = fget(td, args->fd, 0, &fp)) != 0) -#else - if ((error = fget(td, args->fd, &fp)) != 0) + cap_rights_init(&rights, CAP_IOCTL), #endif + &fp)) != 0) { return (error); + } cmd = args->cmd; /* diff --git a/sys/dev/amr/amr_linux.c b/sys/dev/amr/amr_linux.c index 44e858b..5b1a17f 100644 --- a/sys/dev/amr/amr_linux.c +++ b/sys/dev/amr/amr_linux.c @@ -72,10 +72,12 @@ MODULE_DEPEND(amr, linux, 1, 1, 1); static int amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; - if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p); fdrop(fp, p); diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 541624f..9a6ae72 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -2601,14 +2601,14 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, static int guest_buttons; int w, x0, y0; - /* TouchPad PS/2 absolute mode message format + /* TouchPad PS/2 absolute mode message format with capFourButtons: * * Bits: 7 6 5 4 3 2 1 0 (LSB) * ------------------------------------------------ * ipacket[0]: 1 0 W3 W2 0 W1 R L * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8 * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 - * ipacket[3]: 1 1 Yc Xc 0 W0 D U + * ipacket[3]: 1 1 Yc Xc 0 W0 D^R U^L * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 * @@ -2622,6 +2622,21 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, * Y: y position * Z: pressure * + * Without capFourButtons but with nExtendeButtons and/or capMiddle + * + * Bits: 7 6 5 4 3 2 1 0 (LSB) + * ------------------------------------------------------ + * ipacket[3]: 1 1 Yc Xc 0 W0 E^R M^L + * ipacket[4]: X7 X6 X5 X4 X3|b7 X2|b5 X1|b3 X0|b1 + * ipacket[5]: Y7 Y6 Y5 Y4 Y3|b8 Y2|b6 Y1|b4 Y0|b2 + * + * Legend: + * M: Middle physical mouse button + * E: Extended mouse buttons reported instead of low bits of X and Y + * b1-b8: Extended mouse buttons + * Only ((nExtendedButtons + 1) >> 1) bits are used in packet + * 4 and 5, for reading X and Y value they should be zeroed. + * * Absolute reportable limits: 0 - 6143. * Typical bezel limits: 1472 - 5472. * Typical edge marings: 1632 - 5312. @@ -2675,8 +2690,10 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, w = 4; } - /* Handle packets from the guest device */ - /* XXX Documentation? */ + /* + * Handle packets from the guest device. See: + * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1 + */ if (w == 3 && sc->synhw.capPassthrough) { *x = ((pb->ipacket[1] & 0x10) ? pb->ipacket[4] - 256 : pb->ipacket[4]); @@ -2704,36 +2721,49 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, touchpad_buttons |= MOUSE_BUTTON3DOWN; if (sc->synhw.capExtended && sc->synhw.capFourButtons) { - if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0) + if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01) touchpad_buttons |= MOUSE_BUTTON4DOWN; - if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0) + if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02) touchpad_buttons |= MOUSE_BUTTON5DOWN; - } - - /* - * In newer pads - bit 0x02 in the third byte of - * the packet indicates that we have an extended - * button press. - */ - /* XXX Documentation? */ - if (pb->ipacket[3] & 0x02) { - /* - * if directional_scrolls is not 1, we treat any of - * the scrolling directions as middle-click. - */ - if (sc->syninfo.directional_scrolls) { - if (pb->ipacket[4] & 0x01) - touchpad_buttons |= MOUSE_BUTTON4DOWN; - if (pb->ipacket[5] & 0x01) - touchpad_buttons |= MOUSE_BUTTON5DOWN; - if (pb->ipacket[4] & 0x02) - touchpad_buttons |= MOUSE_BUTTON6DOWN; - if (pb->ipacket[5] & 0x02) - touchpad_buttons |= MOUSE_BUTTON7DOWN; - } else { - if ((pb->ipacket[4] & 0x0F) || - (pb->ipacket[5] & 0x0F)) + } else if (sc->synhw.capExtended && sc->synhw.capMiddle) { + /* Middle Button */ + if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01) + touchpad_buttons |= MOUSE_BUTTON2DOWN; + } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) { + /* Extended Buttons */ + if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { + if (sc->syninfo.directional_scrolls) { + if (pb->ipacket[4] & 0x01) + touchpad_buttons |= MOUSE_BUTTON4DOWN; + if (pb->ipacket[5] & 0x01) + touchpad_buttons |= MOUSE_BUTTON5DOWN; + if (pb->ipacket[4] & 0x02) + touchpad_buttons |= MOUSE_BUTTON6DOWN; + if (pb->ipacket[5] & 0x02) + touchpad_buttons |= MOUSE_BUTTON7DOWN; + } else { touchpad_buttons |= MOUSE_BUTTON2DOWN; + } + + /* + * Zero out bits used by extended buttons to avoid + * misinterpretation of the data absolute position. + * + * The bits represented by + * + * (nExtendedButtons + 1) >> 1 + * + * will be masked out in both bytes. + * The mask for n bits is computed with the formula + * + * (1 << n) - 1 + */ + int maskedbits = 0; + int mask = 0; + maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; + mask = (1 << maskedbits) - 1; + pb->ipacket[4] &= ~(mask); + pb->ipacket[5] &= ~(mask); } } @@ -4440,15 +4470,20 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) buttons = 0; synhw.capExtended = (status[0] & 0x80) != 0; if (synhw.capExtended) { - synhw.capPassthrough = (status[2] & 0x80) != 0; - synhw.capSleep = (status[2] & 0x10) != 0; - synhw.capFourButtons = (status[2] & 0x08) != 0; - synhw.capMultiFinger = (status[2] & 0x02) != 0; - synhw.capPalmDetect = (status[2] & 0x01) != 0; + synhw.nExtendedQueries = (status[0] & 0x70) != 0; + synhw.capMiddle = (status[0] & 0x04) != 0; + synhw.capPassthrough = (status[2] & 0x80) != 0; + synhw.capSleep = (status[2] & 0x10) != 0; + synhw.capFourButtons = (status[2] & 0x08) != 0; + synhw.capMultiFinger = (status[2] & 0x02) != 0; + synhw.capPalmDetect = (status[2] & 0x01) != 0; if (verbose >= 2) { printf(" Extended capabilities:\n"); printf(" capExtended: %d\n", synhw.capExtended); + printf(" capMiddle: %d\n", synhw.capMiddle); + printf(" nExtendedQueries: %d\n", + synhw.nExtendedQueries); printf(" capPassthrough: %d\n", synhw.capPassthrough); printf(" capSleep: %d\n", synhw.capSleep); printf(" capFourButtons: %d\n", synhw.capFourButtons); @@ -4457,16 +4492,27 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) } /* - * If we have bits set in status[0] & 0x70, then we can load + * If nExtendedQueries is 1 or greater, then the TouchPad + * supports this number of extended queries. We can load * more information about buttons using query 0x09. */ - if ((status[0] & 0x70) != 0) { + if (synhw.capExtended && synhw.nExtendedQueries) { if (mouse_ext_command(kbdc, 0x09) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); - buttons = (status[1] & 0xf0) >> 4; + synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; + /* + * Add the number of extended buttons to the total + * button support count, including the middle button + * if capMiddle support bit is set. + */ + buttons = synhw.nExtendedButtons + synhw.capMiddle; } else + /* + * If the capFourButtons support bit is set, + * add a fourth button to the total button count. + */ buttons = synhw.capFourButtons ? 1 : 0; } if (verbose >= 2) { @@ -4477,6 +4523,12 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) } /* + * Add the default number of 3 buttons to the total + * count of supported buttons reported above. + */ + buttons += 3; + + /* * Read the mode byte. * * XXX: Note the Synaptics documentation also defines the first @@ -4503,7 +4555,6 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) /* "Commit" the Set Mode Byte command sent above. */ set_mouse_sampling_rate(kbdc, 20); - buttons += 3; VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); if (sc != NULL) { diff --git a/sys/dev/cfi/cfi_bus_nexus.c b/sys/dev/cfi/cfi_bus_nexus.c index 1b317e6..4e1fa4e 100644 --- a/sys/dev/cfi/cfi_bus_nexus.c +++ b/sys/dev/cfi/cfi_bus_nexus.c @@ -4,6 +4,11 @@ * Copyright (c) 2009 Sam Leffler, Errno Consulting * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c index 083f5fc..f318ebc 100644 --- a/sys/dev/cfi/cfi_core.c +++ b/sys/dev/cfi/cfi_core.c @@ -1,7 +1,13 @@ /*- * Copyright (c) 2007, Juniper Networks, Inc. + * Copyright (c) 2012-2013, SRI International * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -49,6 +55,8 @@ __FBSDID("$FreeBSD$"); #include <dev/cfi/cfi_reg.h> #include <dev/cfi/cfi_var.h> +static void cfi_add_sysctls(struct cfi_softc *); + extern struct cdevsw cfi_cdevsw; char cfi_driver_name[] = "cfi"; @@ -262,6 +270,7 @@ cfi_attach(device_t dev) struct cfi_softc *sc; u_int blksz, blocks; u_int r, u; + uint64_t mtoexp, ttoexp; #ifdef CFI_SUPPORT_STRATAFLASH uint64_t ppr; char name[KENV_MNAMELEN], value[32]; @@ -279,11 +288,79 @@ cfi_attach(device_t dev) sc->sc_tag = rman_get_bustag(sc->sc_res); sc->sc_handle = rman_get_bushandle(sc->sc_res); - /* Get time-out values for erase and write. */ - sc->sc_write_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_WRITE); - sc->sc_erase_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_ERASE); - sc->sc_write_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_WRITE); - sc->sc_erase_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_ERASE); + /* Get time-out values for erase, write, and buffer write. */ + ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_ERASE); + mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_ERASE); + if (ttoexp == 0) { + device_printf(dev, "erase timeout == 0, using 2^16ms\n"); + ttoexp = 16; + } + if (ttoexp > 41) { + device_printf(dev, "insane timeout: 2^%jdms\n", ttoexp); + return (EINVAL); + } + if (mtoexp == 0) { + device_printf(dev, "max erase timeout == 0, using 2^%jdms\n", + ttoexp + 4); + mtoexp = 4; + } + if (ttoexp + mtoexp > 41) { + device_printf(dev, "insane max erase timeout: 2^%jd\n", + ttoexp + mtoexp); + return (EINVAL); + } + sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE] = SBT_1MS * (1ULL << ttoexp); + sc->sc_max_timeouts[CFI_TIMEOUT_ERASE] = + sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE] * (1ULL << mtoexp); + + ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_WRITE); + mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_WRITE); + if (ttoexp == 0) { + device_printf(dev, "write timeout == 0, using 2^18ns\n"); + ttoexp = 18; + } + if (ttoexp > 51) { + device_printf(dev, "insane write timeout: 2^%jdus\n", ttoexp); + return (EINVAL); + } + if (mtoexp == 0) { + device_printf(dev, "max write timeout == 0, using 2^%jdms\n", + ttoexp + 4); + mtoexp = 4; + } + if (ttoexp + mtoexp > 51) { + device_printf(dev, "insane max write timeout: 2^%jdus\n", + ttoexp + mtoexp); + return (EINVAL); + } + sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE] = SBT_1US * (1ULL << ttoexp); + sc->sc_max_timeouts[CFI_TIMEOUT_WRITE] = + sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE] * (1ULL << mtoexp); + + ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_BUFWRITE); + mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_BUFWRITE); + /* Don't check for 0, it means not-supported. */ + if (ttoexp > 51) { + device_printf(dev, "insane write timeout: 2^%jdus\n", ttoexp); + return (EINVAL); + } + if (ttoexp + mtoexp > 51) { + device_printf(dev, "insane max write timeout: 2^%jdus\n", + ttoexp + mtoexp); + return (EINVAL); + } + sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] = + SBT_1US * (1ULL << cfi_read_qry(sc, CFI_QRY_TTO_BUFWRITE)); + sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE] = + sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] * + (1ULL << cfi_read_qry(sc, CFI_QRY_MTO_BUFWRITE)); + + /* Get the maximum size of a multibyte program */ + if (sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] != 0) + sc->sc_maxbuf = 1 << (cfi_read_qry(sc, CFI_QRY_MAXBUF) | + cfi_read_qry(sc, CFI_QRY_MAXBUF) << 8); + else + sc->sc_maxbuf = 0; /* Get erase regions. */ sc->sc_regions = cfi_read_qry(sc, CFI_QRY_NREGIONS); @@ -317,6 +394,8 @@ cfi_attach(device_t dev) "%s%u", cfi_driver_name, u); sc->sc_nod->si_drv1 = sc; + cfi_add_sysctls(sc); + #ifdef CFI_SUPPORT_STRATAFLASH /* * Store the Intel factory PPR in the environment. In some @@ -337,6 +416,45 @@ cfi_attach(device_t dev) return (0); } +static void +cfi_add_sysctls(struct cfi_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *children; + + ctx = device_get_sysctl_ctx(sc->sc_dev); + children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); + + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "typical_erase_timout_count", + CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_ERASE], + 0, "Number of times the typical erase timeout was exceeded"); + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "max_erase_timout_count", + CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_ERASE], 0, + "Number of times the maximum erase timeout was exceeded"); + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "typical_write_timout_count", + CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_WRITE], 0, + "Number of times the typical write timeout was exceeded"); + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "max_write_timout_count", + CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_WRITE], 0, + "Number of times the maximum write timeout was exceeded"); + if (sc->sc_maxbuf > 0) { + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "typical_bufwrite_timout_count", + CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_BUFWRITE], 0, + "Number of times the typical buffered write timeout was " + "exceeded"); + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, + "max_bufwrite_timout_count", + CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_BUFWRITE], 0, + "Number of times the maximum buffered write timeout was " + "exceeded"); + } +} + int cfi_detach(device_t dev) { @@ -351,17 +469,22 @@ cfi_detach(device_t dev) } static int -cfi_wait_ready(struct cfi_softc *sc, u_int ofs, u_int timeout) +cfi_wait_ready(struct cfi_softc *sc, u_int ofs, sbintime_t start, + enum cfi_wait_cmd cmd) { - int done, error; + int done, error, tto_exceeded; uint32_t st0 = 0, st = 0; + sbintime_t now; done = 0; error = 0; - timeout *= 10; - while (!done && !error && timeout) { - DELAY(100); - timeout--; + tto_exceeded = 0; + while (!done && !error) { + /* + * Save time before we start so we always do one check + * after the timeout has expired. + */ + now = sbinuptime(); switch (sc->sc_cmdset) { case CFI_VEND_INTEL_ECS: @@ -390,6 +513,25 @@ cfi_wait_ready(struct cfi_softc *sc, u_int ofs, u_int timeout) done = ((st & 0x40) == (st0 & 0x40)) ? 1 : 0; break; } + + if (tto_exceeded || + now > start + sc->sc_typical_timeouts[cmd]) { + if (!tto_exceeded) { + tto_exceeded = 1; + sc->sc_tto_counts[cmd]++; +#ifdef CFI_DEBUG_TIMEOUT + device_printf(sc->sc_dev, + "typical timeout exceeded (cmd %d)", cmd); +#endif + } + if (now > start + sc->sc_max_timeouts[cmd]) { + sc->sc_mto_counts[cmd]++; +#ifdef CFI_DEBUG_TIMEOUT + device_printf(sc->sc_dev, + "max timeout exceeded (cmd %d)", cmd); +#endif + } + } } if (!done && !error) error = ETIMEDOUT; @@ -405,9 +547,12 @@ cfi_write_block(struct cfi_softc *sc) uint8_t *x8; uint16_t *x16; uint32_t *x32; - } ptr; + } ptr, cpyprt; register_t intr; - int error, i; + int error, i, neederase = 0; + uint32_t st; + u_int wlen; + sbintime_t start; /* Intel flash must be unlocked before modification */ switch (sc->sc_cmdset) { @@ -419,31 +564,124 @@ cfi_write_block(struct cfi_softc *sc) break; } - /* Erase the block. */ - switch (sc->sc_cmdset) { - case CFI_VEND_INTEL_ECS: - case CFI_VEND_INTEL_SCS: - cfi_write(sc, sc->sc_wrofs, CFI_BCS_BLOCK_ERASE); - cfi_write(sc, sc->sc_wrofs, CFI_BCS_CONFIRM); - break; - case CFI_VEND_AMD_SCS: - case CFI_VEND_AMD_ECS: - cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START, - CFI_AMD_ERASE_SECTOR); - cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE); - break; - default: - /* Better safe than sorry... */ - return (ENODEV); - } - error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_erase_timeout); - if (error) - goto out; + /* Check if an erase is required. */ + for (i = 0; i < sc->sc_wrbufsz; i++) + if ((sc->sc_wrbuf[i] & sc->sc_wrbufcpy[i]) != sc->sc_wrbuf[i]) { + neederase = 1; + break; + } + + if (neederase) { + intr = intr_disable(); + start = sbinuptime(); + /* Erase the block. */ + switch (sc->sc_cmdset) { + case CFI_VEND_INTEL_ECS: + case CFI_VEND_INTEL_SCS: + cfi_write(sc, sc->sc_wrofs, CFI_BCS_BLOCK_ERASE); + cfi_write(sc, sc->sc_wrofs, CFI_BCS_CONFIRM); + break; + case CFI_VEND_AMD_SCS: + case CFI_VEND_AMD_ECS: + cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START, + CFI_AMD_ERASE_SECTOR); + cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE); + break; + default: + /* Better safe than sorry... */ + intr_restore(intr); + return (ENODEV); + } + intr_restore(intr); + error = cfi_wait_ready(sc, sc->sc_wrofs, start, + CFI_TIMEOUT_ERASE); + if (error) + goto out; + } else + error = 0; - /* Write the block. */ + /* Write the block using a multibyte write if supported. */ ptr.x8 = sc->sc_wrbuf; + cpyprt.x8 = sc->sc_wrbufcpy; + if (sc->sc_maxbuf > sc->sc_width) { + switch (sc->sc_cmdset) { + case CFI_VEND_INTEL_ECS: + case CFI_VEND_INTEL_SCS: + for (i = 0; i < sc->sc_wrbufsz; i += wlen) { + wlen = MIN(sc->sc_maxbuf, sc->sc_wrbufsz - i); + + intr = intr_disable(); + + start = sbinuptime(); + do { + cfi_write(sc, sc->sc_wrofs + i, + CFI_BCS_BUF_PROG_SETUP); + if (sbinuptime() > start + sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE]) { + error = ETIMEDOUT; + goto out; + } + st = cfi_read(sc, sc->sc_wrofs + i); + } while (! (st & CFI_INTEL_STATUS_WSMS)); + + cfi_write(sc, sc->sc_wrofs + i, + (wlen / sc->sc_width) - 1); + switch (sc->sc_width) { + case 1: + bus_space_write_region_1(sc->sc_tag, + sc->sc_handle, sc->sc_wrofs + i, + ptr.x8 + i, wlen); + break; + case 2: + bus_space_write_region_2(sc->sc_tag, + sc->sc_handle, sc->sc_wrofs + i, + ptr.x16 + i / 2, wlen / 2); + break; + case 4: + bus_space_write_region_4(sc->sc_tag, + sc->sc_handle, sc->sc_wrofs + i, + ptr.x32 + i / 4, wlen / 4); + break; + } + + cfi_write(sc, sc->sc_wrofs + i, + CFI_BCS_CONFIRM); + + intr_restore(intr); + + error = cfi_wait_ready(sc, sc->sc_wrofs + i, + start, CFI_TIMEOUT_BUFWRITE); + if (error != 0) + goto out; + } + goto out; + default: + /* Fall through to single word case */ + break; + } + + } + + /* Write the block one byte/word at a time. */ for (i = 0; i < sc->sc_wrbufsz; i += sc->sc_width) { + /* Avoid writing unless we are actually changing bits */ + if (!neederase) { + switch (sc->sc_width) { + case 1: + if(*(ptr.x8 + i) == *(cpyprt.x8 + i)) + continue; + break; + case 2: + if(*(ptr.x16 + i / 2) == *(cpyprt.x16 + i / 2)) + continue; + break; + case 4: + if(*(ptr.x32 + i / 4) == *(cpyprt.x32 + i / 4)) + continue; + break; + } + } + /* * Make sure the command to start a write and the * actual write happens back-to-back without any @@ -451,6 +689,7 @@ cfi_write_block(struct cfi_softc *sc) */ intr = intr_disable(); + start = sbinuptime(); switch (sc->sc_cmdset) { case CFI_VEND_INTEL_ECS: case CFI_VEND_INTEL_SCS: @@ -464,21 +703,22 @@ cfi_write_block(struct cfi_softc *sc) switch (sc->sc_width) { case 1: bus_space_write_1(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x8)++); + sc->sc_wrofs + i, *(ptr.x8 + i)); break; case 2: bus_space_write_2(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x16)++); + sc->sc_wrofs + i, *(ptr.x16 + i / 2)); break; case 4: bus_space_write_4(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x32)++); + sc->sc_wrofs + i, *(ptr.x32 + i / 4)); break; } - + intr_restore(intr); - error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_write_timeout); + error = cfi_wait_ready(sc, sc->sc_wrofs, start, + CFI_TIMEOUT_WRITE); if (error) goto out; } @@ -576,6 +816,7 @@ cfi_intel_set_oem_pr(struct cfi_softc *sc, uint64_t id) #ifdef CFI_ARMEDANDDANGEROUS register_t intr; int i, error; + sbintime_t start; #endif if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) @@ -585,11 +826,12 @@ cfi_intel_set_oem_pr(struct cfi_softc *sc, uint64_t id) #ifdef CFI_ARMEDANDDANGEROUS for (i = 7; i >= 4; i--, id >>= 16) { intr = intr_disable(); + start = sbinuptime(); cfi_write(sc, 0, CFI_INTEL_PP_SETUP); cfi_put16(sc, CFI_INTEL_PR(i), id&0xffff); intr_restore(intr); - error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, - sc->sc_write_timeout); + error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, start, + CFI_TIMEOUT_WRITE); if (error) break; } @@ -629,6 +871,7 @@ cfi_intel_set_plr(struct cfi_softc *sc) #ifdef CFI_ARMEDANDDANGEROUS register_t intr; int error; + sbintime_t start; #endif if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) return EOPNOTSUPP; @@ -638,10 +881,12 @@ cfi_intel_set_plr(struct cfi_softc *sc) /* worthy of console msg */ device_printf(sc->sc_dev, "set PLR\n"); intr = intr_disable(); + binuptime(&start); cfi_write(sc, 0, CFI_INTEL_PP_SETUP); cfi_put16(sc, CFI_INTEL_PLR, 0xFFFD); intr_restore(intr); - error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, sc->sc_write_timeout); + error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, start, + CFI_TIMEOUT_WRITE); cfi_write(sc, 0, CFI_BCS_READ_ARRAY); return error; #else diff --git a/sys/dev/cfi/cfi_dev.c b/sys/dev/cfi/cfi_dev.c index d511eac..7d1f92b 100644 --- a/sys/dev/cfi/cfi_dev.c +++ b/sys/dev/cfi/cfi_dev.c @@ -1,7 +1,13 @@ /*- * Copyright (c) 2007, Juniper Networks, Inc. + * Copyright (c) 2012-2013, SRI International * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -72,7 +78,8 @@ struct cdevsw cfi_cdevsw = { * Begin writing into a new block/sector. We read the sector into * memory and keep updating that, until we move into another sector * or the process stops writing. At that time we write the whole - * sector to flash (see cfi_block_finish). + * sector to flash (see cfi_block_finish). To avoid unneeded erase + * cycles, keep a pristine copy of the sector on hand. */ int cfi_block_start(struct cfi_softc *sc, u_int ofs) @@ -116,6 +123,8 @@ cfi_block_start(struct cfi_softc *sc, u_int ofs) break; } } + sc->sc_wrbufcpy = malloc(sc->sc_wrbufsz, M_TEMP, M_WAITOK); + memcpy(sc->sc_wrbufcpy, sc->sc_wrbuf, sc->sc_wrbufsz); sc->sc_writing = 1; return (0); } @@ -131,6 +140,7 @@ cfi_block_finish(struct cfi_softc *sc) error = cfi_write_block(sc); free(sc->sc_wrbuf, M_TEMP); + free(sc->sc_wrbufcpy, M_TEMP); sc->sc_wrbuf = NULL; sc->sc_wrbufsz = 0; sc->sc_wrofs = 0; diff --git a/sys/dev/cfi/cfi_disk.c b/sys/dev/cfi/cfi_disk.c index f5bcb1b..7980722 100644 --- a/sys/dev/cfi/cfi_disk.c +++ b/sys/dev/cfi/cfi_disk.c @@ -1,7 +1,13 @@ /*- * Copyright (c) 2009 Sam Leffler, Errno Consulting + * Copyright (c) 2012-2013, SRI International * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: diff --git a/sys/dev/cfi/cfi_reg.h b/sys/dev/cfi/cfi_reg.h index 7c22211..c810e3f 100644 --- a/sys/dev/cfi/cfi_reg.h +++ b/sys/dev/cfi/cfi_reg.h @@ -1,7 +1,13 @@ /*- * Copyright (c) 2007, Juniper Networks, Inc. + * Copyright (c) 2012-2013, SRI International * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -44,8 +50,8 @@ struct cfi_qry { u_char max_vcc; u_char min_vpp; u_char max_vpp; - u_char tto_byte_write; /* 2**n milliseconds. */ - u_char tto_buf_write; /* 2**n milliseconds. */ + u_char tto_byte_write; /* 2**n microseconds. */ + u_char tto_buf_write; /* 2**n microseconds. */ u_char tto_block_erase; /* 2**n milliseconds. */ u_char tto_chip_erase; /* 2**n milliseconds. */ u_char mto_byte_write; /* 2**n times typical t/o. */ @@ -70,12 +76,15 @@ struct cfi_qry { #define CFI_QRY_VEND offsetof(struct cfi_qry, pri_vend) #define CFI_QRY_TTO_WRITE offsetof(struct cfi_qry, tto_byte_write) +#define CFI_QRY_TTO_BUFWRITE offsetof(struct cfi_qry, tto_buf_write) #define CFI_QRY_TTO_ERASE offsetof(struct cfi_qry, tto_block_erase) #define CFI_QRY_MTO_WRITE offsetof(struct cfi_qry, mto_byte_write) +#define CFI_QRY_MTO_BUFWRITE offsetof(struct cfi_qry, mto_buf_write) #define CFI_QRY_MTO_ERASE offsetof(struct cfi_qry, mto_block_erase) #define CFI_QRY_SIZE offsetof(struct cfi_qry, size) #define CFI_QRY_IFACE offsetof(struct cfi_qry, iface) +#define CFI_QRY_MAXBUF offsetof(struct cfi_qry, max_buf_write_size) #define CFI_QRY_NREGIONS offsetof(struct cfi_qry, nregions) #define CFI_QRY_REGION0 offsetof(struct cfi_qry, region) #define CFI_QRY_REGION(x) (CFI_QRY_REGION0 + (x) * 4) @@ -102,6 +111,7 @@ struct cfi_qry { #define CFI_BCS_ERASE_SUSPEND 0xb0 #define CFI_BCS_ERASE_RESUME 0xd0 /* Equals CONFIRM */ #define CFI_BCS_CONFIRM 0xd0 +#define CFI_BCS_BUF_PROG_SETUP 0xe8 #define CFI_BCS_READ_ARRAY 0xff /* Intel commands. */ diff --git a/sys/dev/cfi/cfi_var.h b/sys/dev/cfi/cfi_var.h index 15c7769..e218a4d 100644 --- a/sys/dev/cfi/cfi_var.h +++ b/sys/dev/cfi/cfi_var.h @@ -1,7 +1,13 @@ /*- * Copyright (c) 2007, Juniper Networks, Inc. + * Copyright (c) 2012-2013, SRI International * All rights reserved. * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research + * programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,6 +38,12 @@ #ifndef _DEV_CFI_VAR_H_ #define _DEV_CFI_VAR_H_ +enum cfi_wait_cmd { + CFI_TIMEOUT_ERASE, + CFI_TIMEOUT_WRITE, + CFI_TIMEOUT_BUFWRITE +}; + struct cfi_region { u_int r_blocks; u_int r_blksz; @@ -51,13 +63,18 @@ struct cfi_softc { struct cfi_region *sc_region; /* Array of region info. */ u_int sc_cmdset; - u_int sc_erase_timeout; - u_int sc_write_timeout; + sbintime_t sc_typical_timeouts[3]; + sbintime_t sc_max_timeouts[3]; + u_int sc_tto_counts[3]; + u_int sc_mto_counts[3]; + + u_int sc_maxbuf; struct cdev *sc_nod; struct proc *sc_opened; /* Process that has us opened. */ u_char *sc_wrbuf; + u_char *sc_wrbufcpy; u_int sc_wrbufsz; u_int sc_wrofs; u_int sc_writing; diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index 9e1dc80..17f4adb 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -1007,7 +1007,7 @@ calc_opt2p(struct adapter *sc, struct port_info *pi, int rxqid, opt2 |= F_TSTAMPS_EN; if (tcpopt->sack) opt2 |= F_SACK_EN; - if (tcpopt->wsf > 0) + if (tcpopt->wsf <= 14) opt2 |= F_WND_SCALE_EN; } diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c index ce84e3d..e3fda18 100644 --- a/sys/dev/filemon/filemon.c +++ b/sys/dev/filemon/filemon.c @@ -138,12 +138,6 @@ filemon_dtr(void *data) } } -#if __FreeBSD_version < 900041 -#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), (a3)) -#else -#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), CAP_WRITE | CAP_SEEK, (a3)) -#endif - static int filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, struct thread *td) @@ -151,13 +145,21 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, int error = 0; struct filemon *filemon; struct proc *p; +#if __FreeBSD_version >= 900041 + cap_rights_t rights; +#endif devfs_get_cdevpriv((void **) &filemon); switch (cmd) { /* Set the output file descriptor. */ case FILEMON_SET_FD: - if ((error = FGET_WRITE(td, *(int *)data, &filemon->fp)) == 0) + error = fget_write(td, *(int *)data, +#if __FreeBSD_version >= 900041 + cap_rights_init(&rights, CAP_PWRITE), +#endif + &filemon->fp); + if (error == 0) /* Write the file header. */ filemon_comment(filemon); break; diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index d61f7aa..6abb10c 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -131,7 +131,7 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) } if (npins == 0) { - device_printf(child, "empty pin mask"); + device_printf(child, "empty pin mask\n"); return (EINVAL); } diff --git a/sys/dev/gxemul/cons/gxemul_cons.c b/sys/dev/gxemul/cons/gxemul_cons.c index b83aa94..cb3b000 100644 --- a/sys/dev/gxemul/cons/gxemul_cons.c +++ b/sys/dev/gxemul/cons/gxemul_cons.c @@ -99,18 +99,16 @@ static void gxemul_cons_timeout(void *); * XXXRW: Should be using FreeBSD's bus routines here, but they are not * available until later in the boot. */ -typedef uint64_t paddr_t; -typedef uint64_t vaddr_t; -static inline vaddr_t -mips_phys_to_uncached(paddr_t phys) +static inline vm_offset_t +mips_phys_to_uncached(vm_paddr_t phys) { return (MIPS_PHYS_TO_DIRECT_UNCACHED(phys)); } static inline uint8_t -mips_ioread_uint8(vaddr_t vaddr) +mips_ioread_uint8(vm_offset_t vaddr) { uint8_t v; @@ -119,7 +117,7 @@ mips_ioread_uint8(vaddr_t vaddr) } static inline void -mips_iowrite_uint8(vaddr_t vaddr, uint8_t v) +mips_iowrite_uint8(vm_offset_t vaddr, uint8_t v) { __asm__ __volatile__ ("sb %0, 0(%1)" : : "r" (v), "r" (vaddr)); diff --git a/sys/dev/gxemul/disk/gxemul_disk.c b/sys/dev/gxemul/disk/gxemul_disk.c index 8cf52e4..3b7e649 100644 --- a/sys/dev/gxemul/disk/gxemul_disk.c +++ b/sys/dev/gxemul/disk/gxemul_disk.c @@ -214,7 +214,14 @@ gxemul_disk_read(unsigned diskid, void *buf, off_t off) if (off < 0 || off % GXEMUL_DISK_DEV_BLOCKSIZE != 0) return (EINVAL); +#ifdef _LP64 GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET, (uint64_t)off); +#else + GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET_LO, + (uint32_t)(off & 0xffffffff)); + GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET_HI, + (uint32_t)((off >> 32) & 0xffffffff)); +#endif GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_DISKID, diskid); GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_START, GXEMUL_DISK_DEV_START_READ); switch (GXEMUL_DISK_DEV_READ(GXEMUL_DISK_DEV_STATUS)) { @@ -280,7 +287,15 @@ gxemul_disk_write(unsigned diskid, const void *buf, off_t off) if (off < 0 || off % GXEMUL_DISK_DEV_BLOCKSIZE != 0) return (EINVAL); +#ifdef _LP64 GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET, (uint64_t)off); +#else + GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET_LO, + (uint32_t)(off & 0xffffffff)); + GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_OFFSET_HI, + (uint32_t)((off >> 32) & 0xffffffff)); +#endif + GXEMUL_DISK_DEV_WRITE(GXEMUL_DISK_DEV_DISKID, diskid); dst = GXEMUL_DISK_DEV_FUNCTION(GXEMUL_DISK_DEV_BLOCK); diff --git a/sys/dev/gxemul/disk/gxemul_diskreg.h b/sys/dev/gxemul/disk/gxemul_diskreg.h index c3460e5..f837944 100644 --- a/sys/dev/gxemul/disk/gxemul_diskreg.h +++ b/sys/dev/gxemul/disk/gxemul_diskreg.h @@ -36,16 +36,28 @@ #define GXEMUL_DISK_DEV_ID_START (0x0000) #define GXEMUL_DISK_DEV_ID_END (0x0100) -#define GXEMUL_DISK_DEV_OFFSET (0x0000) +#ifdef _LP64 +#define GXEMUL_DISK_DEV_OFFSET (0x0000) +#else +#define GXEMUL_DISK_DEV_OFFSET_LO (0x0000) +#define GXEMUL_DISK_DEV_OFFSET_HI (0x0008) +#endif #define GXEMUL_DISK_DEV_DISKID (0x0010) #define GXEMUL_DISK_DEV_START (0x0020) #define GXEMUL_DISK_DEV_STATUS (0x0030) #define GXEMUL_DISK_DEV_BLOCK (0x4000) +#ifdef _LP64 #define GXEMUL_DISK_DEV_FUNCTION(f) \ (volatile uint64_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_DISK_DEV_BASE + (f)) #define GXEMUL_DISK_DEV_READ(f) \ (volatile uint64_t)*GXEMUL_DISK_DEV_FUNCTION(f) +#else +#define GXEMUL_DISK_DEV_FUNCTION(f) \ + (volatile uint32_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_DISK_DEV_BASE + (f)) +#define GXEMUL_DISK_DEV_READ(f) \ + (volatile uint32_t)*GXEMUL_DISK_DEV_FUNCTION(f) +#endif #define GXEMUL_DISK_DEV_WRITE(f, v) \ *GXEMUL_DISK_DEV_FUNCTION(f) = (v) diff --git a/sys/dev/gxemul/ether/gxreg.h b/sys/dev/gxemul/ether/gxreg.h index e67f43d..a528250 100644 --- a/sys/dev/gxemul/ether/gxreg.h +++ b/sys/dev/gxemul/ether/gxreg.h @@ -40,10 +40,17 @@ #define GXEMUL_ETHER_DEV_COMMAND (0x4020) #define GXEMUL_ETHER_DEV_MAC (0x4040) +#ifdef _LP64 #define GXEMUL_ETHER_DEV_FUNCTION(f) \ (volatile uint64_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_ETHER_DEV_BASE + (f)) #define GXEMUL_ETHER_DEV_READ(f) \ (volatile uint64_t)*GXEMUL_ETHER_DEV_FUNCTION(f) +#else +#define GXEMUL_ETHER_DEV_FUNCTION(f) \ + (volatile uint32_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_ETHER_DEV_BASE + (f)) +#define GXEMUL_ETHER_DEV_READ(f) \ + (volatile uint32_t)*GXEMUL_ETHER_DEV_FUNCTION(f) +#endif #define GXEMUL_ETHER_DEV_WRITE(f, v) \ *GXEMUL_ETHER_DEV_FUNCTION(f) = (v) diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c index 880bcaa..a60e096 100644 --- a/sys/dev/hwpmc/hwpmc_logging.c +++ b/sys/dev/hwpmc/hwpmc_logging.c @@ -570,6 +570,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) { int error; struct proc *p; + cap_rights_t rights; /* * As long as it is possible to get a LOR between pmc_sx lock and @@ -593,7 +594,8 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) po->po_file)); /* get a reference to the file state */ - error = fget_write(curthread, logfd, CAP_WRITE, &po->po_file); + error = fget_write(curthread, logfd, + cap_rights_init(&rights, CAP_WRITE), &po->po_file); if (error) goto error; diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 86242d9..8e5eac8 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -2026,11 +2026,7 @@ pmc_allocate_owner_descriptor(struct proc *p) /* allocate space for N pointers and one descriptor struct */ po = malloc(sizeof(struct pmc_owner), M_PMC, M_WAITOK|M_ZERO); - po->po_sscount = po->po_error = po->po_flags = po->po_logprocmaps = 0; - po->po_file = NULL; po->po_owner = p; - po->po_kthread = NULL; - LIST_INIT(&po->po_pmcs); LIST_INSERT_HEAD(poh, po, po_next); /* insert into hash table */ TAILQ_INIT(&po->po_logbuffers); @@ -2156,8 +2152,6 @@ pmc_allocate_pmc_descriptor(void) struct pmc *pmc; pmc = malloc(sizeof(struct pmc), M_PMC, M_WAITOK|M_ZERO); - pmc->pm_owner = NULL; - LIST_INIT(&pmc->pm_targets); PMCDBG(PMC,ALL,1, "allocate-pmc -> pmc=%p", pmc); diff --git a/sys/dev/hwpmc/hwpmc_mpc7xxx.c b/sys/dev/hwpmc/hwpmc_mpc7xxx.c new file mode 100644 index 0000000..93b5c74 --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_mpc7xxx.c @@ -0,0 +1,748 @@ +/*- + * Copyright (c) 2011 Justin Hibbits + * Copyright (c) 2005, Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/pmc.h> +#include <sys/pmckern.h> +#include <sys/systm.h> + +#include <machine/pmc_mdep.h> +#include <machine/spr.h> +#include <machine/cpu.h> + +#include "hwpmc_powerpc.h" + +#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ + PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ + PMC_CAP_THRESHOLD | PMC_CAP_READ | \ + PMC_CAP_WRITE | PMC_CAP_INVERT | \ + PMC_CAP_QUALIFIER) + +#define PPC_SET_PMC1SEL(r, x) ((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x)) +#define PPC_SET_PMC2SEL(r, x) ((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x)) +#define PPC_SET_PMC3SEL(r, x) ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x)) +#define PPC_SET_PMC4SEL(r, x) ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x)) +#define PPC_SET_PMC5SEL(r, x) ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x)) +#define PPC_SET_PMC6SEL(r, x) ((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x)) + +/* Change this when we support more than just the 7450. */ +#define MPC7XXX_MAX_PMCS 6 + +#define MPC7XXX_PMC_HAS_OVERFLOWED(x) (mpc7xxx_pmcn_read(x) & (0x1 << 31)) + +/* + * Things to improve on this: + * - It stops (clears to 0) the PMC and resets it at every context switch + * currently. + */ + +/* + * This should work for every 32-bit PowerPC implementation I know of (G3 and G4 + * specifically). + */ + +struct powerpc_event_code_map { + enum pmc_event pe_ev; /* enum value */ + uint8_t pe_counter_mask; /* Which counter this can be counted in. */ + uint8_t pe_code; /* numeric code */ +}; + +#define PPC_PMC_MASK1 0 +#define PPC_PMC_MASK2 1 +#define PPC_PMC_MASK3 2 +#define PPC_PMC_MASK4 3 +#define PPC_PMC_MASK5 4 +#define PPC_PMC_MASK6 5 +#define PPC_PMC_MASK_ALL 0x3f +#define PMC_POWERPC_EVENT(id, mask, number) \ + { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } + +static struct powerpc_event_code_map powerpc_event_codes[] = { + PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), + PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), + PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), + PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4), + PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5), + PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7), + PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8), + PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9), + PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10), + PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11), + PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12), + PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13), + PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14), + PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15), + PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16), + PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17), + PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18), + PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19), + PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20), + PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21), + PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22), + PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23), + PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24), + PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25), + PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26), + PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27), + PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28), + PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29), + PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30), + PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31), + PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32), + PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33), + PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34), + PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35), + PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36), + PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37), + PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38), + PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39), + PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40), + PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41), + PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42), + PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43), + PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44), + PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45), + PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46), + PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47), + PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48), + PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49), + PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50), + PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51), + PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52), + PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53), + PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54), + PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55), + PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56), + PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57), + PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58), + PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59), + PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60), + PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61), + PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62), + PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63), + PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64), + PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65), + PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66), + PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67), + PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68), + PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70), + PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71), + PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72), + PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73), + PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74), + PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75), + PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76), + PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77), + PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78), + PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79), + PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80), + PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81), + PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82), + PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83), + PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84), + PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85), + PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86), + PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87), + PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88), + PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89), + PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90), + PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91), + PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92), + PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93), + PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94), + PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23), + PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24), + PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25), + PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26), + PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27), + PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28), + PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29), + PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30), + PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31), + PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32), + PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33), + PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34), + PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35), + PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36), + PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37), + PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38), + PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39), + PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40), + PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41), + PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42), + PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43), + PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44), + PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45), + PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46), + PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47), + PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48), + PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49), + PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50), + PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51), + PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52), + PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53), + PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54), + PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55), + PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56), + PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57), + PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58), + PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59), + PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60), + PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61), + PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62), + PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8), + PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9), + PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10), + PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11), + PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12), + PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13), + PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14), + PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15), + PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16), + PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17), + PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18), + PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19), + PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20), + PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21), + PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22), + PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23), + PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24), + PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25), + PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26), + PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27), + PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28), + PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29), + PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30), + PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31), + PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14), + PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15), + PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16), + PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17), + PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18), + PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19), + PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20), + PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21), + PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22), + PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23), + PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24), + PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25), + PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26), + PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27), + PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28), + PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29), + PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30), + PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2), + PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3), + PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4), + PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5), + PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6), + PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7), + PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8), + PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9), + PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10), + PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11), + PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13), + PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14), + PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15), + PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16), + PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17), + PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18), + PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19), + PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20), + PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8), + PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9), + PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10), + PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11), + PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16), + PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17), + PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19), + PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20), + PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21), + PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22), + PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23), + PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24), + PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25), + PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26), + PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27), + PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28), + PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42), + PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43), + PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44), + PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45), + PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46), + PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47), + PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48), + PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49), + PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50), + PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56), + PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) +}; + +const size_t powerpc_event_codes_size = + sizeof(powerpc_event_codes) / sizeof(powerpc_event_codes[0]); + +static pmc_value_t +mpc7xxx_pmcn_read(unsigned int pmc) +{ + switch (pmc) { + case 0: + return mfspr(SPR_PMC1); + break; + case 1: + return mfspr(SPR_PMC2); + break; + case 2: + return mfspr(SPR_PMC3); + break; + case 3: + return mfspr(SPR_PMC4); + break; + case 4: + return mfspr(SPR_PMC5); + break; + case 5: + return mfspr(SPR_PMC6); + default: + panic("Invalid PMC number: %d\n", pmc); + } +} + +static void +mpc7xxx_pmcn_write(unsigned int pmc, uint32_t val) +{ + switch (pmc) { + case 0: + mtspr(SPR_PMC1, val); + break; + case 1: + mtspr(SPR_PMC2, val); + break; + case 2: + mtspr(SPR_PMC3, val); + break; + case 3: + mtspr(SPR_PMC4, val); + break; + case 4: + mtspr(SPR_PMC5, val); + break; + case 5: + mtspr(SPR_PMC6, val); + break; + default: + panic("Invalid PMC number: %d\n", pmc); + } +} + +static int +mpc7xxx_read_pmc(int cpu, int ri, pmc_value_t *v) +{ + struct pmc *pm; + pmc_value_t tmp; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + KASSERT(pm, + ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, + ri)); + + tmp = mpc7xxx_pmcn_read(ri); + PMCDBG(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + else + *v = tmp; + + return 0; +} + +static int +mpc7xxx_write_pmc(int cpu, int ri, pmc_value_t v) +{ + struct pmc *pm; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); + + PMCDBG(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); + + mpc7xxx_pmcn_write(ri, v); + + return 0; +} + +static int +mpc7xxx_config_pmc(int cpu, int ri, struct pmc *pm) +{ + struct pmc_hw *phw; + + PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + + KASSERT(pm == NULL || phw->phw_pmc == NULL, + ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", + __LINE__, pm, phw->phw_pmc)); + + phw->phw_pmc = pm; + + return 0; +} + +static int +mpc7xxx_start_pmc(int cpu, int ri) +{ + uint32_t config; + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_mmcr; + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + pm = phw->phw_pmc; + config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; + + /* Enable the PMC. */ + switch (ri) { + case 0: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 1: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 2: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + case 3: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 4: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + case 5: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + default: + break; + } + + /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which + * are Freeze flags. + */ + config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; + + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr &= ~SPR_MMCR0_FC; + pmc_mmcr |= config; + mtspr(SPR_MMCR0, pmc_mmcr); + + return 0; +} + +static int +mpc7xxx_stop_pmc(int cpu, int ri) +{ + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_mmcr; + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + pm = phw->phw_pmc; + + /* + * Disable the PMCs. + */ + switch (ri) { + case 0: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 1: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 2: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + case 3: + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR0, pmc_mmcr); + break; + case 4: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + case 5: + pmc_mmcr = mfspr(SPR_MMCR1); + pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0); + mtspr(SPR_MMCR1, pmc_mmcr); + break; + default: + break; + } + return 0; +} + +static int +mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) +{ + int first_ri, i; + struct pmc_cpu *pc; + struct powerpc_cpu *pac; + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); + PMCDBG(MDP,INI,1,"powerpc-init cpu=%d", cpu); + + powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, + M_WAITOK|M_ZERO); + pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS, + M_PMC, M_WAITOK|M_ZERO); + pc = pmc_pcpu[cpu]; + first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450].pcd_ri; + KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); + + for (i = 0, phw = pac->pc_ppcpmcs; i < MPC7XXX_MAX_PMCS; i++, phw++) { + phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | + PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); + phw->phw_pmc = NULL; + pc->pc_hwpmcs[i + first_ri] = phw; + } + + /* Clear the MMCRs, and set FC, to disable all PMCs. */ + mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); + mtspr(SPR_MMCR1, 0); + + return 0; +} + +static int +mpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu) +{ + uint32_t mmcr0 = mfspr(SPR_MMCR0); + + mmcr0 |= SPR_MMCR0_FC; + mtspr(SPR_MMCR0, mmcr0); + free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); + free(powerpc_pcpu[cpu], M_PMC); + return 0; +} + +static int +mpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm, + const struct pmc_op_pmcallocate *a) +{ + enum pmc_event pe; + uint32_t caps, config, counter; + int i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + caps = a->pm_caps; + + pe = a->pm_ev; + for (i = 0; i < powerpc_event_codes_size; i++) { + if (powerpc_event_codes[i].pe_ev == pe) { + config = powerpc_event_codes[i].pe_code; + counter = powerpc_event_codes[i].pe_counter_mask; + break; + } + } + if (i == powerpc_event_codes_size) + return (EINVAL); + + if ((counter & (1 << ri)) == 0) + return (EINVAL); + + if (caps & PMC_CAP_SYSTEM) + config |= POWERPC_PMC_KERNEL_ENABLE; + if (caps & PMC_CAP_USER) + config |= POWERPC_PMC_USER_ENABLE; + if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) + config |= POWERPC_PMC_ENABLE; + + pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; + + PMCDBG(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); + + return 0; +} + +static int +mpc7xxx_release_pmc(int cpu, int ri, struct pmc *pmc) +{ + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + KASSERT(phw->phw_pmc == NULL, + ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); + + return 0; +} + +static int +mpc7xxx_intr(int cpu, struct trapframe *tf) +{ + int i, error, retval; + uint32_t config; + struct pmc *pm; + struct powerpc_cpu *pac; + pmc_value_t v; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); + + PMCDBG(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, + TRAPF_USERMODE(tf)); + + retval = 0; + + pac = powerpc_pcpu[cpu]; + + config = mfspr(SPR_MMCR0); + mtspr(SPR_MMCR0, config | SPR_MMCR0_FC); + + /* + * look for all PMCs that have interrupted: + * - look for a running, sampling PMC which has overflowed + * and which has a valid 'struct pmc' association + * + * If found, we call a helper to process the interrupt. + */ + + for (i = 0; i < MPC7XXX_MAX_PMCS; i++) { + if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || + !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + continue; + } + + if (!MPC7XXX_PMC_HAS_OVERFLOWED(i)) + continue; + + retval = 1; /* Found an interrupting PMC. */ + + if (pm->pm_state != PMC_STATE_RUNNING) + continue; + + /* Stop the PMC, reload count. */ + v = pm->pm_sc.pm_reloadcount; + mpc7xxx_pmcn_write(i, v); + + /* Restart the counter if logging succeeded. */ + error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, + TRAPF_USERMODE(tf)); + if (error != 0) + mpc7xxx_stop_pmc(cpu, i); + atomic_add_int(retval ? &pmc_stats.pm_intr_processed : + &pmc_stats.pm_intr_ignored, 1); + + } + + /* Re-enable PERF exceptions. */ + mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); + + return (retval); +} + +int +pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) +{ + struct pmc_classdep *pcd; + + pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450]; + pcd->pcd_caps = POWERPC_PMC_CAPS; + pcd->pcd_class = PMC_CLASS_PPC7450; + pcd->pcd_num = MPC7XXX_MAX_PMCS; + pcd->pcd_ri = pmc_mdep->pmd_npmc; + pcd->pcd_width = 32; /* All PMCs, even in ppc970, are 32-bit */ + + pcd->pcd_allocate_pmc = mpc7xxx_allocate_pmc; + pcd->pcd_config_pmc = mpc7xxx_config_pmc; + pcd->pcd_pcpu_fini = mpc7xxx_pcpu_fini; + pcd->pcd_pcpu_init = mpc7xxx_pcpu_init; + pcd->pcd_read_pmc = mpc7xxx_read_pmc; + pcd->pcd_release_pmc = mpc7xxx_release_pmc; + pcd->pcd_start_pmc = mpc7xxx_start_pmc; + pcd->pcd_stop_pmc = mpc7xxx_stop_pmc; + pcd->pcd_write_pmc = mpc7xxx_write_pmc; + + pmc_mdep->pmd_npmc += MPC7XXX_MAX_PMCS; + pmc_mdep->pmd_intr = mpc7xxx_intr; + + return 0; +} diff --git a/sys/dev/hwpmc/hwpmc_powerpc.c b/sys/dev/hwpmc/hwpmc_powerpc.c index a54ee62..25a32fa 100644 --- a/sys/dev/hwpmc/hwpmc_powerpc.c +++ b/sys/dev/hwpmc/hwpmc_powerpc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Justin Hibbits + * Copyright (c) 2011,2013 Justin Hibbits * Copyright (c) 2005, Joseph Koshy * All rights reserved. * @@ -36,677 +36,50 @@ __FBSDID("$FreeBSD$"); #include <machine/pmc_mdep.h> #include <machine/spr.h> +#include <machine/pte.h> +#include <machine/sr.h> #include <machine/cpu.h> +#include <machine/vmparam.h> /* For VM_MIN_KERNEL_ADDRESS/VM_MAX_KERNEL_ADDRESS */ -#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ - PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ - PMC_CAP_THRESHOLD | PMC_CAP_READ | \ - PMC_CAP_WRITE | PMC_CAP_INVERT | \ - PMC_CAP_QUALIFIER) +#include "hwpmc_powerpc.h" -#define PPC_SET_PMC1SEL(r, x) ((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x)) -#define PPC_SET_PMC2SEL(r, x) ((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x)) -#define PPC_SET_PMC3SEL(r, x) ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x)) -#define PPC_SET_PMC4SEL(r, x) ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x)) -#define PPC_SET_PMC5SEL(r, x) ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x)) -#define PPC_SET_PMC6SEL(r, x) ((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x)) +#define INKERNEL(x) (((vm_offset_t)(x)) <= VM_MAX_KERNEL_ADDRESS && \ + ((vm_offset_t)(x)) >= VM_MIN_KERNEL_ADDRESS) -/* Change this when we support more than just the 7450. */ -#define PPC_MAX_PMCS 6 - -#define POWERPC_PMC_KERNEL_ENABLE (0x1 << 30) -#define POWERPC_PMC_USER_ENABLE (0x1 << 31) - -#define POWERPC_PMC_ENABLE (POWERPC_PMC_KERNEL_ENABLE | POWERPC_PMC_USER_ENABLE) -#define POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(V) (0x80000000-(V)) -#define POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(P) ((P)-0x80000000) -#define POWERPC_PMC_HAS_OVERFLOWED(x) (powerpc_pmcn_read(x) & (0x1 << 31)) - - -/* - * This should work for every 32-bit PowerPC implementation I know of (G3 and G4 - * specifically). PoewrPC 970 will take more work. - */ - -/* - * Per-processor information. - */ -struct powerpc_cpu { - struct pmc_hw *pc_ppcpmcs; -}; - -static struct powerpc_cpu **powerpc_pcpu; - -struct powerpc_event_code_map { - enum pmc_event pe_ev; /* enum value */ - uint8_t pe_counter_mask; /* Which counter this can be counted in. */ - uint8_t pe_code; /* numeric code */ -}; - -#define PPC_PMC_MASK1 0 -#define PPC_PMC_MASK2 1 -#define PPC_PMC_MASK3 2 -#define PPC_PMC_MASK4 3 -#define PPC_PMC_MASK5 4 -#define PPC_PMC_MASK6 5 -#define PPC_PMC_MASK_ALL 0x3f - -#define PMC_POWERPC_EVENT(id, mask, number) \ - { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } - -static struct powerpc_event_code_map powerpc_event_codes[] = { - PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), - PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), - PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), - PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4), - PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5), - PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7), - PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8), - PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9), - PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10), - PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11), - PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12), - PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13), - PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14), - PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15), - PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16), - PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17), - PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18), - PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19), - PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20), - PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21), - PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22), - PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23), - PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24), - PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25), - PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26), - PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27), - PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28), - PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29), - PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30), - PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31), - PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32), - PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33), - PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34), - PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35), - PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36), - PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37), - PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38), - PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39), - PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40), - PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41), - PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42), - PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43), - PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44), - PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45), - PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46), - PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47), - PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48), - PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49), - PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50), - PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51), - PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52), - PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53), - PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54), - PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55), - PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56), - PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57), - PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58), - PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59), - PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60), - PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61), - PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62), - PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63), - PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64), - PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65), - PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66), - PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67), - PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68), - PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70), - PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71), - PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72), - PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73), - PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74), - PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75), - PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76), - PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77), - PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78), - PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79), - PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80), - PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81), - PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82), - PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83), - PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84), - PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85), - PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86), - PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87), - PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88), - PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89), - PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90), - PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91), - PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92), - PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93), - PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94), - PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23), - PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24), - PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25), - PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26), - PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27), - PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28), - PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29), - PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30), - PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31), - PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32), - PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33), - PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34), - PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35), - PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36), - PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37), - PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38), - PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39), - PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40), - PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41), - PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42), - PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43), - PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44), - PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45), - PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46), - PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47), - PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48), - PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49), - PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50), - PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51), - PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52), - PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53), - PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54), - PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55), - PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56), - PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57), - PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58), - PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59), - PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60), - PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61), - PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62), - PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8), - PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9), - PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10), - PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11), - PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12), - PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13), - PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14), - PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15), - PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16), - PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17), - PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18), - PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19), - PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20), - PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21), - PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22), - PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23), - PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24), - PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25), - PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26), - PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27), - PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28), - PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29), - PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30), - PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31), - PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14), - PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15), - PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16), - PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17), - PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18), - PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19), - PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20), - PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21), - PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22), - PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23), - PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24), - PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25), - PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26), - PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27), - PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28), - PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29), - PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30), - PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2), - PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3), - PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4), - PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5), - PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6), - PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7), - PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8), - PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9), - PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10), - PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11), - PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13), - PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14), - PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15), - PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16), - PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17), - PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18), - PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19), - PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20), - PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8), - PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9), - PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10), - PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11), - PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16), - PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17), - PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19), - PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20), - PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21), - PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22), - PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23), - PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24), - PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25), - PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26), - PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27), - PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28), - PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42), - PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43), - PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44), - PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45), - PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46), - PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47), - PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48), - PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49), - PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50), - PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56), - PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) -}; - -const size_t powerpc_event_codes_size = - sizeof(powerpc_event_codes) / sizeof(powerpc_event_codes[0]); +struct powerpc_cpu **powerpc_pcpu; int pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { - (void) cc; - (void) maxsamples; - (void) tf; - return (0); -} + int frames = 0; + uintptr_t *sp; -static pmc_value_t -powerpc_pmcn_read(unsigned int pmc) -{ - switch (pmc) { - case 0: - return mfspr(SPR_PMC1); - break; - case 1: - return mfspr(SPR_PMC2); - break; - case 2: - return mfspr(SPR_PMC3); - break; - case 3: - return mfspr(SPR_PMC4); - break; - case 4: - return mfspr(SPR_PMC5); - break; - case 5: - return mfspr(SPR_PMC6); - default: - panic("Invalid PMC number: %d\n", pmc); - } -} - -static void -powerpc_pmcn_write(unsigned int pmc, uint32_t val) -{ - switch (pmc) { - case 0: - mtspr(SPR_PMC1, val); - break; - case 1: - mtspr(SPR_PMC2, val); - break; - case 2: - mtspr(SPR_PMC3, val); - break; - case 3: - mtspr(SPR_PMC4, val); - break; - case 4: - mtspr(SPR_PMC5, val); - break; - case 5: - mtspr(SPR_PMC6, val); - break; - default: - panic("Invalid PMC number: %d\n", pmc); - } -} - -static int -powerpc_allocate_pmc(int cpu, int ri, struct pmc *pm, - const struct pmc_op_pmcallocate *a) -{ - enum pmc_event pe; - uint32_t caps, config, counter; - int i; + cc[frames++] = tf->srr0; + sp = (uintptr_t *)tf->fixreg[1]; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - caps = a->pm_caps; - - /* - * TODO: Check actual class for different generations. - */ - if (a->pm_class != PMC_CLASS_PPC7450) - return (EINVAL); - pe = a->pm_ev; - for (i = 0; i < powerpc_event_codes_size; i++) { - if (powerpc_event_codes[i].pe_ev == pe) { - config = powerpc_event_codes[i].pe_code; - counter = powerpc_event_codes[i].pe_counter_mask; + for (frames = 1; frames < maxsamples; frames++) { + if (!INKERNEL(sp)) break; - } - } - if (i == powerpc_event_codes_size) - return (EINVAL); - - if ((counter & (1 << ri)) == 0) - return (EINVAL); - - if (caps & PMC_CAP_SYSTEM) - config |= POWERPC_PMC_KERNEL_ENABLE; - if (caps & PMC_CAP_USER) - config |= POWERPC_PMC_USER_ENABLE; - if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) - config |= POWERPC_PMC_ENABLE; - - pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; - - PMCDBG(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); - - return 0; -} - -static int -powerpc_read_pmc(int cpu, int ri, pmc_value_t *v) -{ - struct pmc *pm; - pmc_value_t tmp; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - tmp = powerpc_pmcn_read(ri); - PMCDBG(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; - - return 0; -} - -static int -powerpc_write_pmc(int cpu, int ri, pmc_value_t v) -{ - struct pmc *pm; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); - - PMCDBG(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); - - powerpc_pmcn_write(ri, v); - - return 0; -} - -static int -powerpc_config_pmc(int cpu, int ri, struct pmc *pm) -{ - struct pmc_hw *phw; - - PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - - KASSERT(pm == NULL || phw->phw_pmc == NULL, - ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", - __LINE__, pm, phw->phw_pmc)); - - phw->phw_pmc = pm; - - return 0; -} - -static int -powerpc_start_pmc(int cpu, int ri) -{ - uint32_t config; - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_mmcr; - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; - config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; - - /* Enable the PMC. */ - switch (ri) { - case 0: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 1: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 2: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - case 3: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 4: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - case 5: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - default: - break; + cc[frames++] = *(sp + 1); + sp = (uintptr_t *)*sp; } - - /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which - * are Freeze flags. - */ - config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; - - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr &= ~SPR_MMCR0_FC; - pmc_mmcr |= config; - mtspr(SPR_MMCR0, pmc_mmcr); - - return 0; -} - -static int -powerpc_stop_pmc(int cpu, int ri) -{ - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_mmcr; - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; - - /* - * Disable the PMCs. - */ - switch (ri) { - case 0: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 1: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 2: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - case 3: - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR0, pmc_mmcr); - break; - case 4: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - case 5: - pmc_mmcr = mfspr(SPR_MMCR1); - pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0); - mtspr(SPR_MMCR1, pmc_mmcr); - break; - default: - break; - } - return 0; -} - -static int -powerpc_release_pmc(int cpu, int ri, struct pmc *pmc) -{ - struct pmc_hw *phw; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - KASSERT(phw->phw_pmc == NULL, - ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); - - return 0; + return (frames); } static int powerpc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) { - return 0; + return (0); } static int powerpc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) { - return 0; -} - -static int -powerpc_intr(int cpu, struct trapframe *tf) -{ - int i, error, retval; - uint32_t config; - struct pmc *pm; - struct powerpc_cpu *pac; - pmc_value_t v; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); - - PMCDBG(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, - TRAPF_USERMODE(tf)); - - retval = 0; - - pac = powerpc_pcpu[cpu]; - - /* - * look for all PMCs that have interrupted: - * - look for a running, sampling PMC which has overflowed - * and which has a valid 'struct pmc' association - * - * If found, we call a helper to process the interrupt. - */ - - for (i = 0; i < PPC_MAX_PMCS; i++) { - if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || - !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - continue; - } - - if (!POWERPC_PMC_HAS_OVERFLOWED(i)) - continue; - - retval = 1; /* Found an interrupting PMC. */ - - if (pm->pm_state != PMC_STATE_RUNNING) - continue; - - /* Stop the PMC, reload count. */ - v = pm->pm_sc.pm_reloadcount; - config = mfspr(SPR_MMCR0); - - mtspr(SPR_MMCR0, config | SPR_MMCR0_FC); - powerpc_pmcn_write(i, v); - - /* Restart the counter if logging succeeded. */ - error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, - TRAPF_USERMODE(tf)); - mtspr(SPR_MMCR0, config); - if (error != 0) - powerpc_stop_pmc(cpu, i); - atomic_add_int(retval ? &pmc_stats.pm_intr_processed : - &pmc_stats.pm_intr_ignored, 1); - - } - - /* Re-enable PERF exceptions. */ - mtspr(SPR_MMCR0, mfspr(SPR_MMCR0) | SPR_MMCR0_PMXE); - - return (retval); + return (0); } -static int +int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) { int error; @@ -715,8 +88,6 @@ powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[powerpc,%d], illegal CPU %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC_MAX_PMCS, - ("[powerpc,%d] row-index %d out of range", __LINE__, ri)); phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; snprintf(powerpc_name, sizeof(powerpc_name), "POWERPC-%d", ri); @@ -735,65 +106,20 @@ powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) return (0); } -static int +int powerpc_get_config(int cpu, int ri, struct pmc **ppm) { *ppm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - return 0; -} - -static int -powerpc_pcpu_init(struct pmc_mdep *md, int cpu) -{ - int first_ri, i; - struct pmc_cpu *pc; - struct powerpc_cpu *pac; - struct pmc_hw *phw; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); - PMCDBG(MDP,INI,1,"powerpc-init cpu=%d", cpu); - - powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, - M_WAITOK|M_ZERO); - pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC_MAX_PMCS, - M_PMC, M_WAITOK|M_ZERO); - pc = pmc_pcpu[cpu]; - first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450].pcd_ri; - KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); - - for (i = 0, phw = pac->pc_ppcpmcs; i < PPC_MAX_PMCS; i++, phw++) { - phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | - PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); - phw->phw_pmc = NULL; - pc->pc_hwpmcs[i + first_ri] = phw; - } - - /* Clear the MMCRs, and set FC, to disable all PMCs. */ - mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); - mtspr(SPR_MMCR1, 0); - - return 0; -} - -static int -powerpc_pcpu_fini(struct pmc_mdep *md, int cpu) -{ - uint32_t mmcr0 = mfspr(SPR_MMCR0); - - mmcr0 |= SPR_MMCR0_FC; - mtspr(SPR_MMCR0, mmcr0); - free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); - free(powerpc_pcpu[cpu], M_PMC); - return 0; + return (0); } struct pmc_mdep * pmc_md_initialize() { struct pmc_mdep *pmc_mdep; - struct pmc_classdep *pcd; + int error; + uint16_t vers; /* * Allocate space for pointers to PMC HW descriptors and for @@ -807,30 +133,31 @@ pmc_md_initialize() pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; - pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450]; - pcd->pcd_caps = POWERPC_PMC_CAPS; - pcd->pcd_class = PMC_CLASS_PPC7450; - pcd->pcd_num = PPC_MAX_PMCS; - pcd->pcd_ri = pmc_mdep->pmd_npmc; - pcd->pcd_width = 32; /* All PMCs, even in ppc970, are 32-bit */ - - pcd->pcd_allocate_pmc = powerpc_allocate_pmc; - pcd->pcd_config_pmc = powerpc_config_pmc; - pcd->pcd_pcpu_fini = powerpc_pcpu_fini; - pcd->pcd_pcpu_init = powerpc_pcpu_init; - pcd->pcd_describe = powerpc_describe; - pcd->pcd_get_config = powerpc_get_config; - pcd->pcd_read_pmc = powerpc_read_pmc; - pcd->pcd_release_pmc = powerpc_release_pmc; - pcd->pcd_start_pmc = powerpc_start_pmc; - pcd->pcd_stop_pmc = powerpc_stop_pmc; - pcd->pcd_write_pmc = powerpc_write_pmc; + vers = mfpvr() >> 16; - pmc_mdep->pmd_intr = powerpc_intr; pmc_mdep->pmd_switch_in = powerpc_switch_in; pmc_mdep->pmd_switch_out = powerpc_switch_out; - pmc_mdep->pmd_npmc += PPC_MAX_PMCS; + switch (vers) { + case MPC7447A: + case MPC7448: + case MPC7450: + case MPC7455: + case MPC7457: + error = pmc_mpc7xxx_initialize(pmc_mdep); + case IBM970: + case IBM970FX: + case IBM970MP: + default: + error = -1; + break; + } + + if (error != 0) { + pmc_mdep_free(pmc_mdep); + pmc_mdep = NULL; + return NULL; + } return (pmc_mdep); } diff --git a/sys/dev/hwpmc/hwpmc_powerpc.h b/sys/dev/hwpmc/hwpmc_powerpc.h new file mode 100644 index 0000000..a9b54f4 --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_powerpc.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2013 Justin Hibbits + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_HWPMC_POWERPC_H_ +#define _DEV_HWPMC_POWERPC_H_ 1 + +#ifdef _KERNEL + +#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ + PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ + PMC_CAP_THRESHOLD | PMC_CAP_READ | \ + PMC_CAP_WRITE | PMC_CAP_INVERT | \ + PMC_CAP_QUALIFIER) + +#define POWERPC_PMC_KERNEL_ENABLE (0x1 << 30) +#define POWERPC_PMC_USER_ENABLE (0x1 << 31) + +#define POWERPC_PMC_ENABLE (POWERPC_PMC_KERNEL_ENABLE | POWERPC_PMC_USER_ENABLE) +#define POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(V) (0x80000000-(V)) +#define POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (0x80000000-(P)) + +struct powerpc_cpu { + struct pmc_hw *pc_ppcpmcs; +}; + +extern struct powerpc_cpu **powerpc_pcpu; + +extern int pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep); + +extern int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc); +extern int powerpc_get_config(int cpu, int ri, struct pmc **ppm); +#endif /* _KERNEL */ + +#endif /* _DEV_HWPMC_POWERPC_H_ */ diff --git a/sys/dev/ipmi/ipmi_linux.c b/sys/dev/ipmi/ipmi_linux.c index 430bd08..b6b38f2 100644 --- a/sys/dev/ipmi/ipmi_linux.c +++ b/sys/dev/ipmi/ipmi_linux.c @@ -89,11 +89,13 @@ MODULE_DEPEND(ipmi_linux, linux, 1, 1, 1); static int ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; u_long cmd; int error; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); cmd = args->cmd; diff --git a/sys/dev/iscsi_initiator/iscsi.c b/sys/dev/iscsi_initiator/iscsi.c index 4dbf163..4a1cb96 100644 --- a/sys/dev/iscsi_initiator/iscsi.c +++ b/sys/dev/iscsi_initiator/iscsi.c @@ -382,16 +382,19 @@ i_ping(struct cdev *dev) static int i_setsoc(isc_session_t *sp, int fd, struct thread *td) { + cap_rights_t rights; int error = 0; if(sp->soc != NULL) isc_stop_receiver(sp); - error = fget(td, fd, CAP_SOCK_CLIENT, &sp->fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT), &sp->fp); if(error) return error; - if((error = fgetsock(td, fd, CAP_SOCK_CLIENT, &sp->soc, 0)) == 0) { + error = fgetsock(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT), + &sp->soc, 0); + if(error == 0) { sp->td = td; isc_start_receiver(sp); } diff --git a/sys/dev/mfi/mfi_linux.c b/sys/dev/mfi/mfi_linux.c index 3328a66..429d496 100644 --- a/sys/dev/mfi/mfi_linux.c +++ b/sys/dev/mfi/mfi_linux.c @@ -84,6 +84,7 @@ MODULE_DEPEND(mfi, linux, 1, 1, 1); static int mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) { + cap_rights_t rights; struct file *fp; int error; u_long cmd = args->cmd; @@ -97,7 +98,8 @@ mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) break; } - if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p); fdrop(fp, p); diff --git a/sys/dev/ntb/if_ntb/if_ntb.c b/sys/dev/ntb/if_ntb/if_ntb.c index 55b19c5..e86ed53 100644 --- a/sys/dev/ntb/if_ntb/if_ntb.c +++ b/sys/dev/ntb/if_ntb/if_ntb.c @@ -104,7 +104,7 @@ struct ntb_transport_qp { bool client_ready; bool qp_link; - uint8_t qp_num; /* Only 64 QP's are allowed. 0-63 */ + uint8_t qp_num; /* Only 64 QPs are allowed. 0-63 */ struct ntb_rx_info *rx_info; struct ntb_rx_info *remote_rx_info; @@ -279,14 +279,14 @@ ntb_handle_module_events(struct module *m, int what, void *arg) return (err); } -static moduledata_t ntb_transport_mod = { - "ntb_transport", +static moduledata_t if_ntb_mod = { + "if_ntb", ntb_handle_module_events, NULL }; -DECLARE_MODULE(ntb_transport, ntb_transport_mod, SI_SUB_KLD, SI_ORDER_ANY); -MODULE_DEPEND(ntb_transport, ntb_hw, 1, 1, 1); +DECLARE_MODULE(if_ntb, if_ntb_mod, SI_SUB_KLD, SI_ORDER_ANY); +MODULE_DEPEND(if_ntb, ntb_hw, 1, 1, 1); static int ntb_setup_interface() @@ -297,7 +297,7 @@ ntb_setup_interface() net_softc.ntb = devclass_get_softc(devclass_find("ntb_hw"), 0); if (net_softc.ntb == NULL) { - printf("ntb: Can't find devclass\n"); + printf("ntb: Cannot find devclass\n"); return (ENXIO); } @@ -334,14 +334,19 @@ ntb_setup_interface() static int ntb_teardown_interface() { - struct ifnet *ifp = net_softc.ifp; - ntb_transport_link_down(net_softc.qp); + if (net_softc.qp != NULL) + ntb_transport_link_down(net_softc.qp); - ether_ifdetach(ifp); - if_free(ifp); - ntb_transport_free_queue(net_softc.qp); - ntb_transport_free(&net_softc); + if (net_softc.ifp != NULL) { + ether_ifdetach(net_softc.ifp); + if_free(net_softc.ifp); + } + + if (net_softc.qp != NULL) { + ntb_transport_free_queue(net_softc.qp); + ntb_transport_free(&net_softc); + } return (0); } @@ -405,7 +410,7 @@ ntb_start(struct ifnet *ifp) m_length(m_head, NULL)); if (rc != 0) { CTR1(KTR_NTB, - "TX: couldn't tx mbuf %p. Returning to snd q", + "TX: could not tx mbuf %p. Returning to snd q", m_head); if (rc == EAGAIN) { ifp->if_drv_flags |= IFF_DRV_OACTIVE; @@ -475,8 +480,11 @@ ntb_transport_init(struct ntb_softc *ntb) if (rc != 0) goto err; - if (ntb_query_link_status(ntb)) + if (ntb_query_link_status(ntb)) { + if (bootverbose) + device_printf(ntb_get_device(ntb), "link up\n"); callout_reset(&nt->link_work, 0, ntb_transport_link_work, nt); + } return (0); @@ -497,7 +505,7 @@ ntb_transport_free(void *transport) callout_drain(&nt->link_work); - /* verify that all the qp's are freed */ + /* verify that all the qps are freed */ for (i = 0; i < nt->max_qps; i++) if (!test_bit(i, &nt->qp_bitmap)) ntb_transport_free_queue(&nt->qps[i]); @@ -673,6 +681,8 @@ ntb_transport_link_up(struct ntb_transport_qp *qp) return; qp->client_ready = NTB_LINK_UP; + if (bootverbose) + device_printf(ntb_get_device(qp->ntb), "qp client ready\n"); if (qp->transport->transport_link == NTB_LINK_UP) callout_reset(&qp->link_work, 0, ntb_qp_link_work, qp); @@ -709,7 +719,7 @@ ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data, entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q); if (entry == NULL) { - CTR0(KTR_NTB, "TX: couldn't get entry from tx_free_q"); + CTR0(KTR_NTB, "TX: could not get entry from tx_free_q"); return (ENOMEM); } CTR1(KTR_NTB, "TX: got entry %p from tx_free_q", entry); @@ -988,9 +998,13 @@ ntb_transport_event_callback(void *data, enum ntb_hw_event event) switch (event) { case NTB_EVENT_HW_LINK_UP: + if (bootverbose) + device_printf(ntb_get_device(nt->ntb), "HW link up\n"); callout_reset(&nt->link_work, 0, ntb_transport_link_work, nt); break; case NTB_EVENT_HW_LINK_DOWN: + if (bootverbose) + device_printf(ntb_get_device(nt->ntb), "HW link down\n"); ntb_transport_link_cleanup(nt); break; default: @@ -1071,6 +1085,8 @@ ntb_transport_link_work(void *arg) return; nt->transport_link = NTB_LINK_UP; + if (bootverbose) + device_printf(ntb_get_device(ntb), "transport link up\n"); for (i = 0; i < nt->max_qps; i++) { qp = &nt->qps[i]; @@ -1176,6 +1192,8 @@ ntb_qp_link_work(void *arg) qp->qp_link = NTB_LINK_UP; if (qp->event_handler != NULL) qp->event_handler(qp->cb_data, NTB_LINK_UP); + if (bootverbose) + device_printf(ntb_get_device(ntb), "qp link up\n"); } else if (nt->transport_link == NTB_LINK_UP) { callout_reset(&qp->link_work, NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_qp_link_work, qp); diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw.c index 72314dd..019f2a7 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw.c @@ -76,10 +76,18 @@ enum ntb_device_type { NTB_SOC }; +/* Device features and workarounds */ +#define HAS_FEATURE(feature) \ + ((ntb->features & (feature)) != 0) + +#define NTB_BAR_SIZE_4K (1 << 0) +#define NTB_REGS_THRU_MW (1 << 1) + struct ntb_hw_info { uint32_t device_id; - enum ntb_device_type type; const char *desc; + enum ntb_device_type type; + uint64_t features; }; struct ntb_pci_bar_info { @@ -108,6 +116,7 @@ struct ntb_db_cb { struct ntb_softc { device_t device; enum ntb_device_type type; + uint64_t features; struct ntb_pci_bar_info bar_info[NTB_MAX_BARS]; struct ntb_int_info int_info[MAX_MSIX_INTERRUPTS]; @@ -145,26 +154,31 @@ struct ntb_softc { uint8_t link_speed; }; -#define ntb_reg_read(SIZE, offset) \ - bus_space_read_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \ - ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset)) +#define ntb_bar_read(SIZE, bar, offset) \ + bus_space_read_ ## SIZE (ntb->bar_info[(bar)].pci_bus_tag, \ + ntb->bar_info[(bar)].pci_bus_handle, (offset)) +#define ntb_bar_write(SIZE, bar, offset, val) \ + bus_space_write_ ## SIZE (ntb->bar_info[(bar)].pci_bus_tag, \ + ntb->bar_info[(bar)].pci_bus_handle, (offset), (val)) +#define ntb_reg_read(SIZE, offset) ntb_bar_read(SIZE, NTB_CONFIG_BAR, offset) #define ntb_reg_write(SIZE, offset, val) \ - bus_space_write_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \ - ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset), (val)) - -#define ntb_read_1(offset) ntb_reg_read(1, (offset)) -#define ntb_read_2(offset) ntb_reg_read(2, (offset)) -#define ntb_read_4(offset) ntb_reg_read(4, (offset)) -#define ntb_read_8(offset) ntb_reg_read(8, (offset)) -#define ntb_write_1(offset, val) ntb_reg_write(1, (offset), (val)) -#define ntb_write_2(offset, val) ntb_reg_write(2, (offset), (val)) -#define ntb_write_4(offset, val) ntb_reg_write(4, (offset), (val)) -#define ntb_write_8(offset, val) ntb_reg_write(8, (offset), (val)) + ntb_bar_write(SIZE, NTB_CONFIG_BAR, offset, val) +#define ntb_mw_read(SIZE, offset) ntb_bar_read(SIZE, NTB_B2B_BAR_2, offset) +#define ntb_mw_write(SIZE, offset, val) \ + ntb_bar_write(SIZE, NTB_B2B_BAR_2, offset, val) + +typedef int (*bar_map_strategy)(struct ntb_softc *ntb, + struct ntb_pci_bar_info *bar); static int ntb_probe(device_t device); static int ntb_attach(device_t device); static int ntb_detach(device_t device); -static int ntb_map_pci_bar(struct ntb_softc *ntb); +static int ntb_map_pci_bars(struct ntb_softc *ntb); +static int map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy, + struct ntb_pci_bar_info *bar); +static int map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar); +static int map_memory_window_bar(struct ntb_softc *ntb, + struct ntb_pci_bar_info *bar); static void ntb_unmap_pci_bar(struct ntb_softc *ntb); static int ntb_setup_interrupts(struct ntb_softc *ntb); static void ntb_teardown_interrupts(struct ntb_softc *ntb); @@ -178,17 +192,21 @@ static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id); static int ntb_initialize_hw(struct ntb_softc *ntb); static int ntb_setup_xeon(struct ntb_softc *ntb); static int ntb_setup_soc(struct ntb_softc *ntb); +static void configure_soc_secondary_side_bars(struct ntb_softc *ntb); +static void configure_xeon_secondary_side_bars(struct ntb_softc *ntb); static void ntb_handle_heartbeat(void *arg); static void ntb_handle_link_event(struct ntb_softc *ntb, int link_state); static void recover_soc_link(void *arg); static int ntb_check_link_status(struct ntb_softc *ntb); -static bool is_bar_for_data_transfer(int bar_num); +static void save_bar_parameters(struct ntb_pci_bar_info *bar); static struct ntb_hw_info pci_ids[] = { - { 0x3C0D8086, NTB_XEON, "Xeon E5/Core i7 Non-Transparent Bridge B2B" }, - { 0x0C4E8086, NTB_SOC, "Atom Processor S1200 NTB Primary B2B" }, - { 0x0E0D8086, NTB_XEON, "Xeon E5 V2 Non-Transparent Bridge B2B" }, - { 0x00000000, NTB_SOC, NULL } + { 0x3C0D8086, "Xeon E5/Core i7 Non-Transparent Bridge B2B", NTB_XEON, + NTB_REGS_THRU_MW }, + { 0x0C4E8086, "Atom Processor S1200 NTB Primary B2B", NTB_SOC, 0 }, + { 0x0E0D8086, "Xeon E5 V2 Non-Transparent Bridge B2B", NTB_XEON, + NTB_REGS_THRU_MW | NTB_BAR_SIZE_4K }, + { 0x00000000, NULL, NTB_SOC, 0 } }; /* @@ -245,12 +263,13 @@ ntb_attach(device_t device) ntb->device = device; ntb->type = p->type; + ntb->features = p->features; /* Heartbeat timer for NTB_SOC since there is no link interrupt */ callout_init(&ntb->heartbeat_timer, CALLOUT_MPSAFE); callout_init(&ntb->lr_timer, CALLOUT_MPSAFE); - DETACH_ON_ERROR(ntb_map_pci_bar(ntb)); + DETACH_ON_ERROR(ntb_map_pci_bars(ntb)); DETACH_ON_ERROR(ntb_initialize_hw(ntb)); DETACH_ON_ERROR(ntb_setup_interrupts(ntb)); @@ -273,59 +292,122 @@ ntb_detach(device_t device) } static int -ntb_map_pci_bar(struct ntb_softc *ntb) +ntb_map_pci_bars(struct ntb_softc *ntb) { - struct ntb_pci_bar_info *current_bar; - int rc, i; + int rc; ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0); + rc = map_pci_bar(ntb, map_mmr_bar, &ntb->bar_info[NTB_CONFIG_BAR]); + if (rc != 0) + return rc; + ntb->bar_info[NTB_B2B_BAR_1].pci_resource_id = PCIR_BAR(2); + rc = map_pci_bar(ntb, map_memory_window_bar, + &ntb->bar_info[NTB_B2B_BAR_1]); + if (rc != 0) + return rc; + ntb->bar_info[NTB_B2B_BAR_2].pci_resource_id = PCIR_BAR(4); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + rc = map_pci_bar(ntb, map_mmr_bar, + &ntb->bar_info[NTB_B2B_BAR_2]); + else + rc = map_pci_bar(ntb, map_memory_window_bar, + &ntb->bar_info[NTB_B2B_BAR_2]); + if (rc != 0) + return rc; - for (i = 0; i< NTB_MAX_BARS; i++) { - current_bar = &ntb->bar_info[i]; - current_bar->pci_resource = - bus_alloc_resource(ntb->device, - SYS_RES_MEMORY, - ¤t_bar->pci_resource_id, 0, ~0, 1, - RF_ACTIVE); + return (0); +} - if (current_bar->pci_resource == NULL) { - device_printf(ntb->device, - "unable to allocate pci resource\n"); - return (ENXIO); +static int +map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy, + struct ntb_pci_bar_info *bar) +{ + int rc; + + rc = strategy(ntb, bar); + if (rc != 0) { + device_printf(ntb->device, + "unable to allocate pci resource\n"); + } else { + device_printf(ntb->device, + "Bar size = %lx, v %p, p %p\n", + bar->size, bar->vbase, + (void *)(bar->pbase)); + } + return (rc); +} + +static int +map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar) +{ + + bar->pci_resource = bus_alloc_resource_any(ntb->device, SYS_RES_MEMORY, + &bar->pci_resource_id, RF_ACTIVE); + + if (bar->pci_resource == NULL) + return (ENXIO); + else { + save_bar_parameters(bar); + return (0); + } +} + +static int +map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar) +{ + int rc; + uint8_t bar_size_bits = 0; + + bar->pci_resource = bus_alloc_resource_any(ntb->device, + SYS_RES_MEMORY, &bar->pci_resource_id, RF_ACTIVE); + + if (bar->pci_resource == NULL) + return (ENXIO); + else { + save_bar_parameters(bar); + /* + * Ivytown NTB BAR sizes are misreported by the hardware due to + * a hardware issue. To work around this, query the size it + * should be configured to by the device and modify the resource + * to correspond to this new size. The BIOS on systems with this + * problem is required to provide enough address space to allow + * the driver to make this change safely. + * + * Ideally I could have just specified the size when I allocated + * the resource like: + * bus_alloc_resource(ntb->device, + * SYS_RES_MEMORY, &bar->pci_resource_id, 0ul, ~0ul, + * 1ul << bar_size_bits, RF_ACTIVE); + * but the PCI driver does not honor the size in this call, so + * we have to modify it after the fact. + */ + if (HAS_FEATURE(NTB_BAR_SIZE_4K)) { + if (bar->pci_resource_id == PCIR_BAR(2)) + bar_size_bits = pci_read_config(ntb->device, + XEON_PBAR23SZ_OFFSET, 1); + else + bar_size_bits = pci_read_config(ntb->device, + XEON_PBAR45SZ_OFFSET, 1); + rc = bus_adjust_resource(ntb->device, SYS_RES_MEMORY, + bar->pci_resource, bar->pbase, + bar->pbase + (1ul << bar_size_bits) - 1); + if (rc != 0 ) { + device_printf(ntb->device, + "unable to resize bar\n"); + return (rc); + } else + save_bar_parameters(bar); } - else { - current_bar->pci_bus_tag = - rman_get_bustag(current_bar->pci_resource); - current_bar->pci_bus_handle = - rman_get_bushandle(current_bar->pci_resource); - current_bar->pbase = - rman_get_start(current_bar->pci_resource); - current_bar->size = - rman_get_size(current_bar->pci_resource); - current_bar->vbase = - rman_get_virtual(current_bar->pci_resource); - if (is_bar_for_data_transfer(i)) { - /* - * Mark bar region as write combining to improve - * performance. - */ - rc = pmap_change_attr( - (vm_offset_t)current_bar->vbase, - current_bar->size, - VM_MEMATTR_WRITE_COMBINING); - if (rc != 0) { - device_printf(ntb->device, - "Couldn't mark bar as" - " WRITE_COMBINING\n"); - return (rc); - } - } - device_printf(ntb->device, - "Bar size = %lx, v %p, p %p\n", - current_bar->size, current_bar->vbase, - (void *)(current_bar->pbase)); + + /* Mark bar region as write combining to improve performance. */ + rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, + VM_MEMATTR_WRITE_COMBINING); + if (rc != 0) { + device_printf(ntb->device, "unable to mark bar as" + " WRITE_COMBINING\n"); + return (rc); } } return (0); @@ -361,9 +443,9 @@ ntb_setup_interrupts(struct ntb_softc *ntb) * Interrupt. The rest will be unmasked as callbacks are registered. */ if (ntb->type == NTB_SOC) - ntb_write_8(ntb->reg_ofs.pdb_mask, ~0); + ntb_reg_write(8, ntb->reg_ofs.pdb_mask, ~0); else - ntb_write_2(ntb->reg_ofs.pdb_mask, + ntb_reg_write(2, ntb->reg_ofs.pdb_mask, ~(1 << ntb->limits.max_db_bits)); num_vectors = MIN(pci_msix_count(ntb->device), @@ -393,7 +475,8 @@ ntb_setup_interrupts(struct ntb_softc *ntb) int_arg = &ntb->db_cb[i]; } else { if (i == num_vectors - 1) { - interrupt_handler = handle_xeon_event_irq; + interrupt_handler = + handle_xeon_event_irq; int_arg = ntb; } else { interrupt_handler = @@ -413,8 +496,8 @@ ntb_setup_interrupts(struct ntb_softc *ntb) } else { ntb->int_info[0].rid = 0; - ntb->int_info[0].res = bus_alloc_resource_any(ntb->device, SYS_RES_IRQ, - &ntb->int_info[0].rid, RF_SHAREABLE|RF_ACTIVE); + ntb->int_info[0].res = bus_alloc_resource_any(ntb->device, + SYS_RES_IRQ, &ntb->int_info[0].rid, RF_SHAREABLE|RF_ACTIVE); interrupt_handler = ntb_handle_legacy_interrupt; if (ntb->int_info[0].res == NULL) { device_printf(ntb->device, @@ -463,7 +546,7 @@ handle_soc_irq(void *arg) struct ntb_db_cb *db_cb = arg; struct ntb_softc *ntb = db_cb->ntb; - ntb_write_8(ntb->reg_ofs.pdb, (uint64_t) 1 << db_cb->db_num); + ntb_reg_write(8, ntb->reg_ofs.pdb, (uint64_t) 1 << db_cb->db_num); if (db_cb->callback != NULL) db_cb->callback(db_cb->data, db_cb->db_num); @@ -481,7 +564,7 @@ handle_xeon_irq(void *arg) * vectors, with the 4th having a single bit for link * interrupts. */ - ntb_write_2(ntb->reg_ofs.pdb, + ntb_reg_write(2, ntb->reg_ofs.pdb, ((1 << ntb->bits_per_vector) - 1) << (db_cb->db_num * ntb->bits_per_vector)); @@ -501,7 +584,7 @@ handle_xeon_event_irq(void *arg) device_printf(ntb->device, "Error determining link status\n"); /* bit 15 is always the link bit */ - ntb_write_2(ntb->reg_ofs.pdb, 1 << ntb->limits.max_db_bits); + ntb_reg_write(2, ntb->reg_ofs.pdb, 1 << ntb->limits.max_db_bits); } static void @@ -513,7 +596,7 @@ ntb_handle_legacy_interrupt(void *arg) uint16_t pdb16; if (ntb->type == NTB_SOC) { - pdb64 = ntb_read_8(ntb->reg_ofs.pdb); + pdb64 = ntb_reg_read(8, ntb->reg_ofs.pdb); while (pdb64) { i = ffs(pdb64); @@ -521,7 +604,7 @@ ntb_handle_legacy_interrupt(void *arg) handle_soc_irq(&ntb->db_cb[i]); } } else { - pdb16 = ntb_read_2(ntb->reg_ofs.pdb); + pdb16 = ntb_reg_read(2, ntb->reg_ofs.pdb); if ((pdb16 & XEON_DB_HW_LINK) != 0) { handle_xeon_event_irq(ntb); @@ -634,10 +717,15 @@ ntb_setup_xeon(struct ntb_softc *ntb) ntb->limits.msix_cnt = XEON_MSIX_CNT; ntb->bits_per_vector = XEON_DB_BITS_PER_VEC; + configure_xeon_secondary_side_bars(ntb); /* Enable Bus Master and Memory Space on the secondary side */ - ntb_write_2(ntb->reg_ofs.spci_cmd, + ntb_reg_write(2, ntb->reg_ofs.spci_cmd, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + /* Enable link training */ + ntb_reg_write(4, ntb->reg_ofs.lnk_cntl, + NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP); + return (0); } @@ -698,49 +786,63 @@ ntb_setup_soc(struct ntb_softc *ntb) */ pci_write_config(ntb->device, 0xFC, 0x4, 4); - /* - * Some BIOSes aren't filling out the XLAT offsets. - * Check and correct the issue. - */ - if (ntb->dev_type == NTB_DEV_USD) { - if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0) - ntb_write_8(SOC_PBAR2XLAT_OFFSET, - SOC_PBAR2XLAT_USD_ADDR); - - if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0) - ntb_write_8(SOC_PBAR4XLAT_OFFSET, - SOC_PBAR4XLAT_USD_ADDR); + configure_soc_secondary_side_bars(ntb); - if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC) - ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_USD_ADDR); - - if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC) - ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_USD_ADDR); - } else { - if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0) - ntb_write_8(SOC_PBAR2XLAT_OFFSET, - SOC_PBAR2XLAT_DSD_ADDR); + /* Enable Bus Master and Memory Space on the secondary side */ + ntb_reg_write(2, ntb->reg_ofs.spci_cmd, + PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + callout_reset(&ntb->heartbeat_timer, 0, ntb_handle_heartbeat, ntb); - if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0) - ntb_write_8(SOC_PBAR4XLAT_OFFSET, - SOC_PBAR4XLAT_DSD_ADDR); + return (0); +} - if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC) - ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_DSD_ADDR); +static void +configure_soc_secondary_side_bars(struct ntb_softc *ntb) +{ - if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC) - ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_DSD_ADDR); + if (ntb->dev_type == NTB_DEV_USD) { + ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, PBAR2XLAT_USD_ADDR); + ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, PBAR4XLAT_USD_ADDR); + ntb_reg_write(8, SOC_MBAR23_OFFSET, MBAR23_USD_ADDR); + ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR45_USD_ADDR); + } else { + ntb_reg_write(8, SOC_PBAR2XLAT_OFFSET, PBAR2XLAT_DSD_ADDR); + ntb_reg_write(8, SOC_PBAR4XLAT_OFFSET, PBAR4XLAT_DSD_ADDR); + ntb_reg_write(8, SOC_MBAR23_OFFSET, MBAR23_DSD_ADDR); + ntb_reg_write(8, SOC_MBAR45_OFFSET, MBAR45_DSD_ADDR); } +} - /* Enable Bus Master and Memory Space on the secondary side */ - ntb_write_2(ntb->reg_ofs.spci_cmd, - PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - callout_reset(&ntb->heartbeat_timer, 0, ntb_handle_heartbeat, ntb); +static void +configure_xeon_secondary_side_bars(struct ntb_softc *ntb) +{ - return (0); + if (ntb->dev_type == NTB_DEV_USD) { + ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, PBAR2XLAT_USD_ADDR); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + MBAR01_DSD_ADDR); + else + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + PBAR4XLAT_USD_ADDR); + ntb_reg_write(8, XEON_SBAR0BASE_OFFSET, MBAR01_USD_ADDR); + ntb_reg_write(8, XEON_SBAR2BASE_OFFSET, MBAR23_USD_ADDR); + ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, MBAR45_USD_ADDR); + } else { + ntb_reg_write(8, XEON_PBAR2XLAT_OFFSET, PBAR2XLAT_DSD_ADDR); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + MBAR01_USD_ADDR); + else + ntb_reg_write(8, XEON_PBAR4XLAT_OFFSET, + PBAR4XLAT_DSD_ADDR); + ntb_reg_write(8, XEON_SBAR0BASE_OFFSET, MBAR01_DSD_ADDR); + ntb_reg_write(8, XEON_SBAR2BASE_OFFSET, MBAR23_DSD_ADDR); + ntb_reg_write(8, XEON_SBAR4BASE_OFFSET, MBAR45_DSD_ADDR); + } } -/* SOC doesn't have link status interrupt, poll on that platform */ +/* SOC does not have link status interrupt, poll on that platform */ static void ntb_handle_heartbeat(void *arg) { @@ -753,7 +855,7 @@ ntb_handle_heartbeat(void *arg) "Error determining link status\n"); /* Check to see if a link error is the cause of the link down */ if (ntb->link_status == NTB_LINK_DOWN) { - status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); + status32 = ntb_reg_read(4, SOC_LTSSMSTATEJMP_OFFSET); if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) { callout_reset(&ntb->lr_timer, 0, recover_soc_link, ntb); @@ -771,37 +873,37 @@ soc_perform_link_restart(struct ntb_softc *ntb) uint32_t status; /* Driver resets the NTB ModPhy lanes - magic! */ - ntb_write_1(SOC_MODPHY_PCSREG6, 0xe0); - ntb_write_1(SOC_MODPHY_PCSREG4, 0x40); - ntb_write_1(SOC_MODPHY_PCSREG4, 0x60); - ntb_write_1(SOC_MODPHY_PCSREG6, 0x60); + ntb_reg_write(1, SOC_MODPHY_PCSREG6, 0xe0); + ntb_reg_write(1, SOC_MODPHY_PCSREG4, 0x40); + ntb_reg_write(1, SOC_MODPHY_PCSREG4, 0x60); + ntb_reg_write(1, SOC_MODPHY_PCSREG6, 0x60); /* Driver waits 100ms to allow the NTB ModPhy to settle */ pause("ModPhy", hz / 10); /* Clear AER Errors, write to clear */ - status = ntb_read_4(SOC_ERRCORSTS_OFFSET); + status = ntb_reg_read(4, SOC_ERRCORSTS_OFFSET); status &= PCIM_AER_COR_REPLAY_ROLLOVER; - ntb_write_4(SOC_ERRCORSTS_OFFSET, status); + ntb_reg_write(4, SOC_ERRCORSTS_OFFSET, status); /* Clear unexpected electrical idle event in LTSSM, write to clear */ - status = ntb_read_4(SOC_LTSSMERRSTS0_OFFSET); + status = ntb_reg_read(4, SOC_LTSSMERRSTS0_OFFSET); status |= SOC_LTSSMERRSTS0_UNEXPECTEDEI; - ntb_write_4(SOC_LTSSMERRSTS0_OFFSET, status); + ntb_reg_write(4, SOC_LTSSMERRSTS0_OFFSET, status); /* Clear DeSkew Buffer error, write to clear */ - status = ntb_read_4(SOC_DESKEWSTS_OFFSET); + status = ntb_reg_read(4, SOC_DESKEWSTS_OFFSET); status |= SOC_DESKEWSTS_DBERR; - ntb_write_4(SOC_DESKEWSTS_OFFSET, status); + ntb_reg_write(4, SOC_DESKEWSTS_OFFSET, status); - status = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET); + status = ntb_reg_read(4, SOC_IBSTERRRCRVSTS0_OFFSET); status &= SOC_IBIST_ERR_OFLOW; - ntb_write_4(SOC_IBSTERRRCRVSTS0_OFFSET, status); + ntb_reg_write(4, SOC_IBSTERRRCRVSTS0_OFFSET, status); /* Releases the NTB state machine to allow the link to retrain */ - status = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); + status = ntb_reg_read(4, SOC_LTSSMSTATEJMP_OFFSET); status &= ~SOC_LTSSMSTATEJMP_FORCEDETECT; - ntb_write_4(SOC_LTSSMSTATEJMP_OFFSET, status); + ntb_reg_write(4, SOC_LTSSMSTATEJMP_OFFSET, status); } static void @@ -819,7 +921,7 @@ ntb_handle_link_event(struct ntb_softc *ntb, int link_state) event = NTB_EVENT_HW_LINK_UP; if (ntb->type == NTB_SOC) - status = ntb_read_2(ntb->reg_ofs.lnk_stat); + status = ntb_reg_read(2, ntb->reg_ofs.lnk_stat); else status = pci_read_config(ntb->device, XEON_LINK_STATUS_OFFSET, 2); @@ -833,7 +935,7 @@ ntb_handle_link_event(struct ntb_softc *ntb, int link_state) device_printf(ntb->device, "Link Down\n"); ntb->link_status = NTB_LINK_DOWN; event = NTB_EVENT_HW_LINK_DOWN; - /* Don't modify link width/speed, we need it in link recovery */ + /* Do not modify link width/speed, we need it in link recovery */ } /* notify the upper layer if we have an event change */ @@ -852,15 +954,15 @@ recover_soc_link(void *arg) soc_perform_link_restart(ntb); pause("Link", SOC_LINK_RECOVERY_TIME * hz / 1000); - status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); + status32 = ntb_reg_read(4, SOC_LTSSMSTATEJMP_OFFSET); if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) goto retry; - status32 = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET); + status32 = ntb_reg_read(4, SOC_IBSTERRRCRVSTS0_OFFSET); if ((status32 & SOC_IBIST_ERR_OFLOW) != 0) goto retry; - status16 = ntb_read_2(ntb->reg_ofs.lnk_stat); + status16 = ntb_reg_read(2, ntb->reg_ofs.lnk_stat); width = (status16 & NTB_LINK_WIDTH_MASK) >> 4; speed = (status16 & NTB_LINK_SPEED_MASK); if (ntb->link_width != width || ntb->link_speed != speed) @@ -883,7 +985,7 @@ ntb_check_link_status(struct ntb_softc *ntb) uint16_t status; if (ntb->type == NTB_SOC) { - ntb_cntl = ntb_read_4(ntb->reg_ofs.lnk_cntl); + ntb_cntl = ntb_reg_read(4, ntb->reg_ofs.lnk_cntl); if ((ntb_cntl & SOC_CNTL_LINK_DOWN) != 0) link_state = NTB_LINK_DOWN; else @@ -965,9 +1067,9 @@ ntb_register_db_callback(struct ntb_softc *ntb, unsigned int idx, void *data, ntb->db_cb[idx].data = data; /* unmask interrupt */ - mask = ntb_read_2(ntb->reg_ofs.pdb_mask); + mask = ntb_reg_read(2, ntb->reg_ofs.pdb_mask); mask &= ~(1 << (idx * ntb->bits_per_vector)); - ntb_write_2(ntb->reg_ofs.pdb_mask, mask); + ntb_reg_write(2, ntb->reg_ofs.pdb_mask, mask); return (0); } @@ -988,9 +1090,9 @@ ntb_unregister_db_callback(struct ntb_softc *ntb, unsigned int idx) if (idx >= ntb->allocated_interrupts || !ntb->db_cb[idx].callback) return; - mask = ntb_read_2(ntb->reg_ofs.pdb_mask); + mask = ntb_reg_read(2, ntb->reg_ofs.pdb_mask); mask |= 1 << (idx * ntb->bits_per_vector); - ntb_write_2(ntb->reg_ofs.pdb_mask, mask); + ntb_reg_write(2, ntb->reg_ofs.pdb_mask, mask); ntb->db_cb[idx].callback = NULL; } @@ -1091,7 +1193,7 @@ ntb_write_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val) if (idx >= ntb->limits.max_spads) return (EINVAL); - ntb_write_4(ntb->reg_ofs.spad_local + idx * 4, val); + ntb_reg_write(4, ntb->reg_ofs.spad_local + idx * 4, val); return (0); } @@ -1114,7 +1216,7 @@ ntb_read_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val) if (idx >= ntb->limits.max_spads) return (EINVAL); - *val = ntb_read_4(ntb->reg_ofs.spad_local + idx * 4); + *val = ntb_reg_read(4, ntb->reg_ofs.spad_local + idx * 4); return (0); } @@ -1137,7 +1239,10 @@ ntb_write_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val) if (idx >= ntb->limits.max_spads) return (EINVAL); - ntb_write_4(ntb->reg_ofs.spad_remote + idx * 4, val); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + ntb_mw_write(4, XEON_SHADOW_SPAD_OFFSET + idx * 4, val); + else + ntb_reg_write(4, ntb->reg_ofs.spad_remote + idx * 4, val); return (0); } @@ -1160,7 +1265,10 @@ ntb_read_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val) if (idx >= ntb->limits.max_spads) return (EINVAL); - *val = ntb_read_4(ntb->reg_ofs.spad_remote + idx * 4); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + *val = ntb_mw_read(4, XEON_SHADOW_SPAD_OFFSET + idx * 4); + else + *val = ntb_reg_read(4, ntb->reg_ofs.spad_remote + idx * 4); return (0); } @@ -1233,10 +1341,10 @@ ntb_set_mw_addr(struct ntb_softc *ntb, unsigned int mw, uint64_t addr) switch (NTB_MW_TO_BAR(mw)) { case NTB_B2B_BAR_1: - ntb_write_8(ntb->reg_ofs.sbar2_xlat, addr); + ntb_reg_write(8, ntb->reg_ofs.sbar2_xlat, addr); break; case NTB_B2B_BAR_2: - ntb_write_8(ntb->reg_ofs.sbar4_xlat, addr); + ntb_reg_write(8, ntb->reg_ofs.sbar4_xlat, addr); break; } } @@ -1256,11 +1364,16 @@ ntb_ring_sdb(struct ntb_softc *ntb, unsigned int db) { if (ntb->type == NTB_SOC) - ntb_write_8(ntb->reg_ofs.sdb, (uint64_t) 1 << db); + ntb_reg_write(8, ntb->reg_ofs.sdb, (uint64_t) 1 << db); else - ntb_write_2(ntb->reg_ofs.sdb, - ((1 << ntb->bits_per_vector) - 1) << - (db * ntb->bits_per_vector)); + if (HAS_FEATURE(NTB_REGS_THRU_MW)) + ntb_mw_write(2, XEON_SHADOW_PDOORBELL_OFFSET, + ((1 << ntb->bits_per_vector) - 1) << + (db * ntb->bits_per_vector)); + else + ntb_reg_write(2, ntb->reg_ofs.sdb, + ((1 << ntb->bits_per_vector) - 1) << + (db * ntb->bits_per_vector)); } /** @@ -1278,11 +1391,24 @@ ntb_query_link_status(struct ntb_softc *ntb) return (ntb->link_status == NTB_LINK_UP); } -static bool -is_bar_for_data_transfer(int bar_num) +static void +save_bar_parameters(struct ntb_pci_bar_info *bar) { - if ((bar_num > NTB_CONFIG_BAR) && (bar_num < NTB_MAX_BARS)) - return true; - else - return false; + bar->pci_bus_tag = + rman_get_bustag(bar->pci_resource); + bar->pci_bus_handle = + rman_get_bushandle(bar->pci_resource); + bar->pbase = + rman_get_start(bar->pci_resource); + bar->size = + rman_get_size(bar->pci_resource); + bar->vbase = + rman_get_virtual(bar->pci_resource); + +} + +device_t ntb_get_device(struct ntb_softc *ntb) +{ + + return (ntb->device); } diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.h b/sys/dev/ntb/ntb_hw/ntb_hw.h index 4f44031..c6c1274 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw.h +++ b/sys/dev/ntb/ntb_hw/ntb_hw.h @@ -69,5 +69,6 @@ u_long ntb_get_mw_size(struct ntb_softc *ntb, unsigned int mw); void ntb_set_mw_addr(struct ntb_softc *ntb, unsigned int mw, uint64_t addr); void ntb_ring_sdb(struct ntb_softc *ntb, unsigned int db); bool ntb_query_link_status(struct ntb_softc *ntb); +device_t ntb_get_device(struct ntb_softc *ntb); #endif /* _NTB_HW_H_ */ diff --git a/sys/dev/ntb/ntb_hw/ntb_regs.h b/sys/dev/ntb/ntb_hw/ntb_regs.h index 34ad779..bd55a59 100644 --- a/sys/dev/ntb/ntb_hw/ntb_regs.h +++ b/sys/dev/ntb/ntb_hw/ntb_regs.h @@ -39,14 +39,14 @@ #define XEON_MAX_SPADS 16 #define XEON_MAX_COMPAT_SPADS 8 /* Reserve the uppermost bit for link interrupt */ -#define XEON_MAX_DB_BITS 15 +#define XEON_MAX_DB_BITS 15 #define XEON_DB_BITS_PER_VEC 5 #define XEON_DB_HW_LINK 0x8000 #define XEON_PCICMD_OFFSET 0x0504 #define XEON_DEVCTRL_OFFSET 0x0598 -#define XEON_LINK_STATUS_OFFSET 0x01A2 +#define XEON_LINK_STATUS_OFFSET 0x01a2 #define XEON_PBAR2LMT_OFFSET 0x0000 #define XEON_PBAR4LMT_OFFSET 0x0008 @@ -60,13 +60,13 @@ #define XEON_SBAR2BASE_OFFSET 0x0048 #define XEON_SBAR4BASE_OFFSET 0x0050 #define XEON_NTBCNTL_OFFSET 0x0058 -#define XEON_SBDF_OFFSET 0x005C +#define XEON_SBDF_OFFSET 0x005c #define XEON_PDOORBELL_OFFSET 0x0060 #define XEON_PDBMSK_OFFSET 0x0062 #define XEON_SDOORBELL_OFFSET 0x0064 #define XEON_SDBMSK_OFFSET 0x0066 #define XEON_USMEMMISS 0x0070 -#define XEON_SPAD_OFFSET 0x0080 +#define XEON_SPAD_OFFSET 0x0080 #define XEON_SPADSEMA4_OFFSET 0x00c0 #define XEON_WCCNTRL_OFFSET 0x00e0 #define XEON_B2B_SPAD_OFFSET 0x0100 @@ -105,7 +105,7 @@ #define SOC_MODPHY_PCSREG4 0x1c004 #define SOC_MODPHY_PCSREG6 0x1c006 -#define SOC_IP_BASE 0xC000 +#define SOC_IP_BASE 0xc000 #define SOC_DESKEWSTS_OFFSET (SOC_IP_BASE + 0x3024) #define SOC_LTSSMERRSTS0_OFFSET (SOC_IP_BASE + 0x3180) #define SOC_LTSSMSTATEJMP_OFFSET (SOC_IP_BASE + 0x3040) @@ -114,13 +114,15 @@ #define SOC_DESKEWSTS_DBERR (1 << 15) #define SOC_LTSSMERRSTS0_UNEXPECTEDEI (1 << 20) #define SOC_LTSSMSTATEJMP_FORCEDETECT (1 << 2) -#define SOC_IBIST_ERR_OFLOW 0x7FFF7FFF +#define SOC_IBIST_ERR_OFLOW 0x7fff7fff #define NTB_CNTL_BAR23_SNOOP (1 << 2) #define NTB_CNTL_BAR45_SNOOP (1 << 6) #define SOC_CNTL_LINK_DOWN (1 << 16) -#define NTB_PPD_OFFSET 0x00D4 +#define XEON_PBAR23SZ_OFFSET 0x00d0 +#define XEON_PBAR45SZ_OFFSET 0x00d1 +#define NTB_PPD_OFFSET 0x00d4 #define XEON_PPD_CONN_TYPE 0x0003 #define XEON_PPD_DEV_TYPE 0x0010 #define SOC_PPD_INIT_LINK 0x0008 @@ -134,13 +136,19 @@ #define NTB_DEV_DSD 1 #define NTB_DEV_USD 0 -#define SOC_PBAR2XLAT_USD_ADDR 0x0000004000000000 -#define SOC_PBAR4XLAT_USD_ADDR 0x0000008000000000 -#define SOC_MBAR23_USD_ADDR 0x000000410000000C -#define SOC_MBAR45_USD_ADDR 0x000000810000000C -#define SOC_PBAR2XLAT_DSD_ADDR 0x0000004100000000 -#define SOC_PBAR4XLAT_DSD_ADDR 0x0000008100000000 -#define SOC_MBAR23_DSD_ADDR 0x000000400000000C -#define SOC_MBAR45_DSD_ADDR 0x000000800000000C +#define PBAR2XLAT_USD_ADDR 0x0000004000000000 +#define PBAR4XLAT_USD_ADDR 0x0000008000000000 +#define MBAR01_USD_ADDR 0x000000210000000c +#define MBAR23_USD_ADDR 0x000000410000000c +#define MBAR45_USD_ADDR 0x000000810000000c +#define PBAR2XLAT_DSD_ADDR 0x0000004100000000 +#define PBAR4XLAT_DSD_ADDR 0x0000008100000000 +#define MBAR01_DSD_ADDR 0x000000200000000c +#define MBAR23_DSD_ADDR 0x000000400000000c +#define MBAR45_DSD_ADDR 0x000000800000000c + +/* XEON Shadowed MMIO Space */ +#define XEON_SHADOW_PDOORBELL_OFFSET 0x60 +#define XEON_SHADOW_SPAD_OFFSET 0x80 #endif /* _NTB_REGS_H_ */ diff --git a/sys/dev/tdfx/tdfx_linux.c b/sys/dev/tdfx/tdfx_linux.c index 0b769f0..fa39ab1 100644 --- a/sys/dev/tdfx/tdfx_linux.c +++ b/sys/dev/tdfx/tdfx_linux.c @@ -45,6 +45,7 @@ LINUX_IOCTL_SET(tdfx, LINUX_IOCTL_TDFX_MIN, LINUX_IOCTL_TDFX_MAX); static int linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args) { + cap_rights_t rights; int error = 0; u_long cmd = args->cmd & 0xffff; @@ -54,7 +55,8 @@ linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args) struct file *fp; - if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) return (error); /* We simply copy the data and send it right to ioctl */ copyin((caddr_t)args->arg, &d_pio, sizeof(d_pio)); diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index bc971ec..439cd8f 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -243,6 +243,7 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = { UFTDI_DEV(FALCOM, TWIST, UFTDI_TYPE_8U232AM), UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG), UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG), + UFTDI_DEV(FTDI, 232EX, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, 232H, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, 232RL, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, UFTDI_TYPE_AUTO), diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 498d424..e6a32ae 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1547,6 +1547,7 @@ product DLINK DWLG122 0x3c00 DWL-G122 b1 Wireless Adapter product DLINK DUBE100B1 0x3c05 DUB-E100 rev B1 product DLINK RT2870 0x3c09 RT2870 product DLINK RT3072 0x3c0a RT3072 +product DLINK DWA127 0x3c1b DWA-127 Wireless Adapter product DLINK DSB650C 0x4000 10Mbps Ethernet product DLINK DSB650TX1 0x4001 10/100 Ethernet product DLINK DSB650TX 0x4002 10/100 Ethernet @@ -1776,6 +1777,7 @@ product FTDI SERIAL_8U232AM4 0x6004 8U232AM Serial product FTDI SERIAL_232RL 0x6006 FT232RL Serial product FTDI SERIAL_2232C 0x6010 FT2232C Dual port Serial product FTDI 232H 0x6014 FTDI compatible adapter +product FTDI 232EX 0x6015 FTDI compatible adapter product FTDI SERIAL_2232D 0x9e90 FT2232D Dual port Serial product FTDI SERIAL_4232H 0x6011 FT4232H Quad port Serial product FTDI BEAGLEBONE 0xa6d0 BeagleBone diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index aed07a2..5b4587f 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -171,6 +171,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(CYBERTAN, RT2870), RUN_DEV(DLINK, RT2870), RUN_DEV(DLINK, RT3072), + RUN_DEV(DLINK, DWA127), RUN_DEV(DLINK2, DWA130), RUN_DEV(DLINK2, RT2870_1), RUN_DEV(DLINK2, RT2870_2), diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index f757394..93c6007 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -592,6 +592,9 @@ vtnet_setup_features(struct vtnet_softc *sc) vtnet_negotiate_features(sc); + if (virtio_with_feature(dev, VIRTIO_RING_F_EVENT_IDX)) + sc->vtnet_flags |= VTNET_FLAG_EVENT_IDX; + if (virtio_with_feature(dev, VIRTIO_NET_F_MAC)) { /* This feature should always be negotiated. */ sc->vtnet_flags |= VTNET_FLAG_MAC; @@ -1531,7 +1534,7 @@ vtnet_rxq_csum_by_parse(struct vtnet_rxq *rxq, struct mbuf *m, */ #if 0 if_printf(sc->vtnet_ifp, "cksum offload of unsupported " - "protocol eth_type=%#x proto=%d csum_start=%d + "protocol eth_type=%#x proto=%d csum_start=%d " "csum_offset=%d\n", __func__, eth_type, proto, hdr->csum_start, hdr->csum_offset); #endif @@ -2155,6 +2158,8 @@ vtnet_start_locked(struct vtnet_txq *txq, struct ifnet *ifp) sc->vtnet_link_active == 0) return; + vtnet_txq_eof(txq); + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { if (virtqueue_full(vq)) break; @@ -2226,6 +2231,8 @@ vtnet_txq_mq_start_locked(struct vtnet_txq *txq, struct mbuf *m) return (error); } + vtnet_txq_eof(txq); + while ((m = drbr_peek(ifp, br)) != NULL) { error = vtnet_txq_encap(txq, &m); if (error) { @@ -2471,6 +2478,8 @@ vtnet_watchdog(struct vtnet_txq *txq) sc = txq->vtntx_sc; VTNET_TXQ_LOCK(txq); + if (sc->vtnet_flags & VTNET_FLAG_EVENT_IDX) + vtnet_txq_eof(txq); if (txq->vtntx_watchdog == 0 || --txq->vtntx_watchdog) { VTNET_TXQ_UNLOCK(txq); return (0); diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h index 5921103..7f04a93 100644 --- a/sys/dev/virtio/network/if_vtnetvar.h +++ b/sys/dev/virtio/network/if_vtnetvar.h @@ -138,6 +138,7 @@ struct vtnet_softc { #define VTNET_FLAG_MRG_RXBUFS 0x0080 #define VTNET_FLAG_LRO_NOMRG 0x0100 #define VTNET_FLAG_MULTIQ 0x0200 +#define VTNET_FLAG_EVENT_IDX 0x0400 int vtnet_link_active; int vtnet_hdr_size; diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c index beff14c..5eda6cd 100644 --- a/sys/dev/virtio/virtqueue.c +++ b/sys/dev/virtio/virtqueue.c @@ -449,10 +449,10 @@ virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint) switch (hint) { case VQ_POSTPONE_SHORT: - ndesc /= 4; + ndesc = ndesc / 4; break; case VQ_POSTPONE_LONG: - ndesc *= 3 / 4; + ndesc = (ndesc * 3) / 4; break; case VQ_POSTPONE_EMPTIED: break; diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 33f6faf..21fbb41 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -230,7 +230,7 @@ struct xbb_xen_reqlist { int num_children; /** - * Number of I/O requests dispatched to the backend. + * Number of I/O requests still pending on the backend. */ int pendcnt; @@ -327,13 +327,6 @@ struct xbb_xen_req { int nr_512b_sectors; /** - * The number of struct bio requests still outstanding for this - * request on the backend device. This field is only used for - * device (rather than file) backed I/O. - */ - int pendcnt; - - /** * BLKIF_OP code for this request. */ int operation; @@ -1239,6 +1232,8 @@ xbb_get_resources(struct xbb_softc *xbb, struct xbb_xen_reqlist **reqlist, nreq->reqlist = *reqlist; nreq->req_ring_idx = ring_idx; + nreq->id = ring_req->id; + nreq->operation = ring_req->operation; if (xbb->abi != BLKIF_PROTOCOL_NATIVE) { bcopy(ring_req, &nreq->ring_req_storage, sizeof(*ring_req)); @@ -1608,7 +1603,6 @@ xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) req_ring_idx = nreq->req_ring_idx; nr_sects = 0; nseg = ring_req->nr_segments; - nreq->id = ring_req->id; nreq->nr_pages = nseg; nreq->nr_512b_sectors = 0; req_seg_idx = 0; @@ -2062,7 +2056,6 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, { struct xbb_dev_data *dev_data; struct bio *bios[XBB_MAX_SEGMENTS_PER_REQLIST]; - struct xbb_xen_req *nreq; off_t bio_offset; struct bio *bio; struct xbb_sg *xbb_sg; @@ -2080,7 +2073,6 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, bio_idx = 0; if (operation == BIO_FLUSH) { - nreq = STAILQ_FIRST(&reqlist->contig_req_list); bio = g_new_bio(); if (__predict_false(bio == NULL)) { DPRINTF("Unable to allocate bio for BIO_FLUSH\n"); @@ -2094,10 +2086,10 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, bio->bio_offset = 0; bio->bio_data = 0; bio->bio_done = xbb_bio_done; - bio->bio_caller1 = nreq; + bio->bio_caller1 = reqlist; bio->bio_pblkno = 0; - nreq->pendcnt = 1; + reqlist->pendcnt = 1; SDT_PROBE1(xbb, kernel, xbb_dispatch_dev, flush, device_get_unit(xbb->dev)); diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index f18c0fc..b976504 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -309,7 +309,7 @@ fdesc_lookup(ap) /* * No rights to check since 'fp' isn't actually used. */ - if ((error = fget(td, fd, 0, &fp)) != 0) + if ((error = fget(td, fd, NULL, &fp)) != 0) goto bad; /* Check if we're looking up ourselves. */ @@ -445,6 +445,7 @@ fdesc_setattr(ap) struct mount *mp; struct file *fp; struct thread *td = curthread; + cap_rights_t rights; unsigned fd; int error; @@ -459,7 +460,8 @@ fdesc_setattr(ap) /* * Allow setattr where there is an underlying vnode. */ - error = getvnode(td->td_proc->p_fd, fd, CAP_EXTATTR_SET, &fp); + error = getvnode(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) { /* * getvnode() returns EINVAL if the file descriptor is not diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c index 639550a..0b4f19b 100644 --- a/sys/fs/fuse/fuse_vfsops.c +++ b/sys/fs/fuse/fuse_vfsops.c @@ -220,6 +220,7 @@ fuse_vfsop_mount(struct mount *mp) struct file *fp, *fptmp; char *fspec, *subtype; struct vfsoptlist *opts; + cap_rights_t rights; subtype = NULL; max_read_set = 0; @@ -289,7 +290,7 @@ fuse_vfsop_mount(struct mount *mp) FS_DEBUG2G("mntopts 0x%jx\n", (uintmax_t)mntopts); - err = fget(td, fd, CAP_READ, &fp); + err = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp); if (err != 0) { FS_DEBUG("invalid or not opened device: data=%p\n", data); goto out; diff --git a/sys/fs/nfsclient/nfs_clkrpc.c b/sys/fs/nfsclient/nfs_clkrpc.c index 8b0b234..502fec5 100644 --- a/sys/fs/nfsclient/nfs_clkrpc.c +++ b/sys/fs/nfsclient/nfs_clkrpc.c @@ -278,17 +278,15 @@ nfsrvd_cbinit(int terminating) while (nfs_numnfscbd > 0) msleep(&nfs_numnfscbd, NFSDLOCKMUTEXPTR, PZERO, "nfscbdt", 0); - NFSD_UNLOCK(); - svcpool_destroy(nfscbd_pool); - nfscbd_pool = NULL; - } else - NFSD_UNLOCK(); - - nfscbd_pool = svcpool_create("nfscbd", NULL); - nfscbd_pool->sp_rcache = NULL; - nfscbd_pool->sp_assign = NULL; - nfscbd_pool->sp_done = NULL; + } - NFSD_LOCK(); + if (nfscbd_pool == NULL) { + NFSD_UNLOCK(); + nfscbd_pool = svcpool_create("nfscbd", NULL); + nfscbd_pool->sp_rcache = NULL; + nfscbd_pool->sp_assign = NULL; + nfscbd_pool->sp_done = NULL; + NFSD_LOCK(); + } } diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index d7b082b..b198d59 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -1219,10 +1219,11 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap) struct file *fp; struct nfscbd_args nfscbdarg; struct nfsd_nfscbd_args nfscbdarg2; - int error; struct nameidata nd; struct nfscl_dumpmntopts dumpmntopts; + cap_rights_t rights; char *buf; + int error; if (uap->flag & NFSSVC_CBADDSOCK) { error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg)); @@ -1233,10 +1234,10 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap) * pretend that we need them all. It is better to be too * careful than too reckless. */ - if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_CLIENT, &fp)) - != 0) { + error = fget(td, nfscbdarg.sock, + cap_rights_init(&rights, CAP_SOCK_CLIENT), &fp); + if (error) return (error); - } if (fp->f_type != DTYPE_SOCKET) { fdrop(fp, td); return (EPERM); diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index 863c418..4a180c5 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -120,6 +120,7 @@ static vfs_root_t nfs_root; static vfs_statfs_t nfs_statfs; static vfs_sync_t nfs_sync; static vfs_sysctl_t nfs_sysctl; +static vfs_purge_t nfs_purge; /* * nfs vfs operations. @@ -134,6 +135,7 @@ static struct vfsops nfs_vfsops = { .vfs_uninit = ncl_uninit, .vfs_unmount = nfs_unmount, .vfs_sysctl = nfs_sysctl, + .vfs_purge = nfs_purge, }; VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY); @@ -1676,6 +1678,19 @@ nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req) } /* + * Purge any RPCs in progress, so that they will all return errors. + * This allows dounmount() to continue as far as VFS_UNMOUNT() for a + * forced dismount. + */ +static void +nfs_purge(struct mount *mp) +{ + struct nfsmount *nmp = VFSTONFS(mp); + + newnfs_nmcancelreqs(nmp); +} + +/* * Extract the information needed by the nlm from the nfs vnode. */ static void diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index a6a0169..2f9d40a 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -3035,6 +3035,7 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap) struct file *fp; struct nfsd_addsock_args sockarg; struct nfsd_nfsd_args nfsdarg; + cap_rights_t rights; int error; if (uap->flag & NFSSVC_NFSDADDSOCK) { @@ -3046,7 +3047,9 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap) * pretend that we need them all. It is better to be too * careful than too reckless. */ - if ((error = fget(td, sockarg.sock, CAP_SOCK_SERVER, &fp)) != 0) + error = fget(td, sockarg.sock, + cap_rights_init(&rights, CAP_SOCK_SERVER), &fp); + if (error != 0) goto out; if (fp->f_type != DTYPE_SOCKET) { fdrop(fp, td); diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 6819fcc..18e3cc4 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -621,21 +621,19 @@ end: * to close it when this situation occur. */ static void -g_eli_last_close(struct g_eli_softc *sc) +g_eli_last_close(void *arg, int flags __unused) { struct g_geom *gp; - struct g_provider *pp; - char ppname[64]; + char gpname[64]; int error; g_topology_assert(); - gp = sc->sc_geom; - pp = LIST_FIRST(&gp->provider); - strlcpy(ppname, pp->name, sizeof(ppname)); - error = g_eli_destroy(sc, TRUE); + gp = arg; + strlcpy(gpname, gp->name, sizeof(gpname)); + error = g_eli_destroy(gp->softc, TRUE); KASSERT(error == 0, ("Cannot detach %s on last close (error=%d).", - ppname, error)); - G_ELI_DEBUG(0, "Detached %s on last close.", ppname); + gpname, error)); + G_ELI_DEBUG(0, "Detached %s on last close.", gpname); } int @@ -665,7 +663,7 @@ g_eli_access(struct g_provider *pp, int dr, int dw, int de) */ if ((sc->sc_flags & G_ELI_FLAG_RW_DETACH) || (sc->sc_flags & G_ELI_FLAG_WOPEN)) { - g_eli_last_close(sc); + g_post_event(g_eli_last_close, gp, M_WAITOK, NULL); } return (0); } @@ -916,6 +914,10 @@ g_eli_destroy(struct g_eli_softc *sc, boolean_t force) if (force) { G_ELI_DEBUG(1, "Device %s is still open, so it " "cannot be definitely removed.", pp->name); + sc->sc_flags |= G_ELI_FLAG_RW_DETACH; + gp->access = g_eli_access; + g_wither_provider(pp, ENXIO); + return (EBUSY); } else { G_ELI_DEBUG(1, "Device %s is still open (r%dw%de%d).", pp->name, diff --git a/sys/geom/part/g_part_ldm.c b/sys/geom/part/g_part_ldm.c index 81abc84..40c2eb8 100644 --- a/sys/geom/part/g_part_ldm.c +++ b/sys/geom/part/g_part_ldm.c @@ -339,8 +339,6 @@ static int g_part_ldm_read(struct g_part_table *, struct g_consumer *); static const char *g_part_ldm_type(struct g_part_table *, struct g_part_entry *, char *, size_t); static int g_part_ldm_write(struct g_part_table *, struct g_consumer *); -static int g_part_ldm_resize(struct g_part_table *, struct g_part_entry *, - struct g_part_parms *); static kobj_method_t g_part_ldm_methods[] = { KOBJMETHOD(g_part_add, g_part_ldm_add), @@ -350,7 +348,6 @@ static kobj_method_t g_part_ldm_methods[] = { KOBJMETHOD(g_part_dumpconf, g_part_ldm_dumpconf), KOBJMETHOD(g_part_dumpto, g_part_ldm_dumpto), KOBJMETHOD(g_part_modify, g_part_ldm_modify), - KOBJMETHOD(g_part_resize, g_part_ldm_resize), KOBJMETHOD(g_part_name, g_part_ldm_name), KOBJMETHOD(g_part_probe, g_part_ldm_probe), KOBJMETHOD(g_part_read, g_part_ldm_read), @@ -1206,14 +1203,6 @@ g_part_ldm_modify(struct g_part_table *basetable, return (ENOSYS); } -static int -g_part_ldm_resize(struct g_part_table *basetable, - struct g_part_entry *baseentry, struct g_part_parms *gpp) -{ - - return (ENOSYS); -} - static const char * g_part_ldm_name(struct g_part_table *table, struct g_part_entry *baseentry, char *buf, size_t bufsz) diff --git a/sys/i386/ibcs2/ibcs2_fcntl.c b/sys/i386/ibcs2/ibcs2_fcntl.c index 2902da7..d061b79 100644 --- a/sys/i386/ibcs2/ibcs2_fcntl.c +++ b/sys/i386/ibcs2/ibcs2_fcntl.c @@ -201,10 +201,12 @@ ibcs2_open(td, uap) free(path, M_TEMP); PROC_LOCK(p); if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { + cap_rights_t rights; struct file *fp; int error; - error = fget(td, td->td_retval[0], CAP_IOCTL, &fp); + error = fget(td, td->td_retval[0], + cap_rights_init(&rights, CAP_IOCTL), &fp); PROC_UNLOCK(p); if (error) return (EBADF); diff --git a/sys/i386/ibcs2/ibcs2_ioctl.c b/sys/i386/ibcs2/ibcs2_ioctl.c index 83e68cd..03fa5f6 100644 --- a/sys/i386/ibcs2/ibcs2_ioctl.c +++ b/sys/i386/ibcs2/ibcs2_ioctl.c @@ -331,10 +331,12 @@ ibcs2_ioctl(td, uap) struct ibcs2_ioctl_args *uap; { struct proc *p = td->td_proc; + cap_rights_t rights; struct file *fp; int error; - if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) { + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) { DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid, uap->fd)); return EBADF; diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 9f382aa..28cd83c 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -326,6 +326,7 @@ ibcs2_getdents(td, uap) register int len, reclen; /* BSD-format */ register caddr_t outp; /* iBCS2-format */ register int resid; /* iBCS2-format */ + cap_rights_t rights; struct file *fp; struct uio auio; struct iovec aiov; @@ -337,7 +338,9 @@ ibcs2_getdents(td, uap) #define BSD_DIRENT(cp) ((struct dirent *)(cp)) #define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -478,6 +481,7 @@ ibcs2_read(td, uap) register int len, reclen; /* BSD-format */ register caddr_t outp; /* iBCS2-format */ register int resid; /* iBCS2-format */ + cap_rights_t rights; struct file *fp; struct uio auio; struct iovec aiov; @@ -490,8 +494,9 @@ ibcs2_read(td, uap) u_long *cookies = NULL, *cookiep; int ncookies; - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, - &fp)) != 0) { + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) { if (error == EINVAL) return sys_read(td, (struct read_args *)uap); else diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index 14d1892..2d79204 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -422,6 +422,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, } */ bsd_args; int error; struct file *fp; + cap_rights_t rights; error = 0; bsd_args.flags = 0; @@ -473,7 +474,9 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, * is done in the FreeBSD mmap(). */ - if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) + error = fget(td, bsd_args.fd, + cap_rights_init(&rights, CAP_MMAP), &fp); + if (error != 0) return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index c070172..7ac1dbb 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -85,20 +85,46 @@ __FBSDID("$FreeBSD$"); #include <machine/specialreg.h> #include <machine/pcpu.h> - - #include <xen/xen-os.h> #include <xen/evtchn.h> #include <xen/xen_intr.h> #include <xen/hypervisor.h> #include <xen/interface/vcpu.h> +/*---------------------------- Extern Declarations ---------------------------*/ +extern struct pcpu __pcpu[]; + +extern void Xhypervisor_callback(void); +extern void failsafe_callback(void); +extern void pmap_lazyfix_action(void); + +/*--------------------------- Forward Declarations ---------------------------*/ +static void assign_cpu_ids(void); +static void set_interrupt_apic_ids(void); +static int start_all_aps(void); +static int start_ap(int apic_id); +static void release_aps(void *dummy); + +/*-------------------------------- Local Types -------------------------------*/ +typedef void call_data_func_t(uintptr_t , uintptr_t); + +/* + * Store data from cpu_add() until later in the boot when we actually setup + * the APs. + */ +struct cpu_info { + int cpu_present:1; + int cpu_bsp:1; + int cpu_disabled:1; +}; + +/*-------------------------------- Global Data -------------------------------*/ +static u_int hyperthreading_cpus; +static cpuset_t hyperthreading_cpus_mask; int mp_naps; /* # of Applications processors */ int boot_cpu_id = -1; /* designated BSP */ -extern struct pcpu __pcpu[]; - static int bootAP; static union descriptor *bootAPgdt; @@ -112,8 +138,6 @@ vm_offset_t smp_tlb_addr1; vm_offset_t smp_tlb_addr2; volatile int smp_tlb_wait; -typedef void call_data_func_t(uintptr_t , uintptr_t); - static u_int logical_cpus; static volatile cpuset_t ipi_nmi_pending; @@ -127,11 +151,7 @@ static volatile int aps_ready = 0; * Store data from cpu_add() until later in the boot when we actually setup * the APs. */ -struct cpu_info { - int cpu_present:1; - int cpu_bsp:1; - int cpu_disabled:1; -} static cpu_info[MAX_APIC_ID + 1]; +static struct cpu_info cpu_info[MAX_APIC_ID + 1]; int cpu_apic_ids[MAXCPU]; int apic_cpuids[MAX_APIC_ID + 1]; @@ -141,22 +161,11 @@ static volatile u_int cpu_ipi_pending[MAXCPU]; static int cpu_logical; static int cpu_cores; -static void assign_cpu_ids(void); -static void set_interrupt_apic_ids(void); -int start_all_aps(void); -static int start_ap(int apic_id); -static void release_aps(void *dummy); - -static u_int hyperthreading_cpus; -static cpuset_t hyperthreading_cpus_mask; - -extern void Xhypervisor_callback(void); -extern void failsafe_callback(void); -extern void pmap_lazyfix_action(void); - +/*------------------------------- Per-CPU Data -------------------------------*/ DPCPU_DEFINE(xen_intr_handle_t, ipi_port[NR_IPIS]); DPCPU_DEFINE(struct vcpu_info *, vcpu_info); +/*------------------------------ Implementation ------------------------------*/ struct cpu_group * cpu_topo(void) { @@ -353,14 +362,14 @@ iv_lazypmap(uintptr_t a, uintptr_t b) /* * These start from "IPI offset" APIC_IPI_INTS */ -static call_data_func_t *ipi_vectors[6] = +static call_data_func_t *ipi_vectors[] = { - iv_rendezvous, - iv_invltlb, - iv_invlpg, - iv_invlrng, - iv_invlcache, - iv_lazypmap, + iv_rendezvous, + iv_invltlb, + iv_invlpg, + iv_invlrng, + iv_invlcache, + iv_lazypmap, }; /* @@ -414,7 +423,8 @@ smp_call_function_interrupt(void *unused) atomic_t *finished = &call_data->finished; /* We only handle function IPIs, not bitmap IPIs */ - if (call_data->func_id < APIC_IPI_INTS || call_data->func_id > IPI_BITMAP_VECTOR) + if (call_data->func_id < APIC_IPI_INTS || + call_data->func_id > IPI_BITMAP_VECTOR) panic("invalid function id %u", call_data->func_id); func = ipi_vectors[call_data->func_id - APIC_IPI_INTS]; @@ -494,14 +504,14 @@ xen_smp_cpu_init(unsigned int cpu) printf("[XEN] IPI cpu=%d port=%d vector=CALL_FUNCTION_VECTOR (%d)\n", cpu, xen_intr_port(irq_handle), CALL_FUNCTION_VECTOR); - return 0; + return (0); fail: xen_intr_unbind(DPCPU_ID_GET(cpu, ipi_port[RESCHEDULE_VECTOR])); DPCPU_ID_SET(cpu, ipi_port[RESCHEDULE_VECTOR], NULL); xen_intr_unbind(DPCPU_ID_GET(cpu, ipi_port[CALL_FUNCTION_VECTOR])); DPCPU_ID_SET(cpu, ipi_port[CALL_FUNCTION_VECTOR], NULL); - return rc; + return (rc); } static void @@ -795,7 +805,7 @@ start_all_aps(void) pmap_invalidate_range(kernel_pmap, 0, NKPT * NBPDR - 1); /* number of APs actually started */ - return mp_naps; + return (mp_naps); } extern uint8_t *pcpu_boot_stack; @@ -900,7 +910,8 @@ cpu_initialize_context(unsigned int cpu) smp_trap_init(ctxt.trap_ctxt); ctxt.ldt_ents = 0; - ctxt.gdt_frames[0] = (uint32_t)((uint64_t)vtomach(bootAPgdt) >> PAGE_SHIFT); + ctxt.gdt_frames[0] = + (uint32_t)((uint64_t)vtomach(bootAPgdt) >> PAGE_SHIFT); ctxt.gdt_ents = 512; #ifdef __i386__ @@ -960,10 +971,10 @@ start_ap(int apic_id) /* Wait up to 5 seconds for it to start. */ for (ms = 0; ms < 5000; ms++) { if (mp_naps > cpus) - return 1; /* return SUCCESS */ + return (1); /* return SUCCESS */ DELAY(1000); } - return 0; /* return FAILURE */ + return (0); /* return FAILURE */ } static void @@ -1026,7 +1037,8 @@ smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2) } static void -smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, vm_offset_t addr1, vm_offset_t addr2) +smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, vm_offset_t addr1, + vm_offset_t addr2) { int cpu, ncpu, othercpus; struct _call_data data; @@ -1262,4 +1274,3 @@ release_aps(void *dummy __unused) SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL); SYSINIT(start_ipis, SI_SUB_SMP, SI_ORDER_ANY, xen_smp_intr_init_cpus, NULL); SYSINIT(start_cpu, SI_SUB_INTR, SI_ORDER_ANY, xen_smp_intr_setup_cpus, NULL); - diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c index 09987fd..186897b 100644 --- a/sys/ia64/ia64/vm_machdep.c +++ b/sys/ia64/ia64/vm_machdep.c @@ -79,7 +79,6 @@ #include <sys/vmmeter.h> #include <sys/kernel.h> #include <sys/mbuf.h> -#include <sys/sf_buf.h> #include <sys/sysctl.h> #include <sys/unistd.h> @@ -353,27 +352,6 @@ cpu_exit(struct thread *td) } /* - * Allocate an sf_buf for the given vm_page. On this machine, however, there - * is no sf_buf object. Instead, an opaque pointer to the given vm_page is - * returned. - */ -struct sf_buf * -sf_buf_alloc(struct vm_page *m, int pri) -{ - - return ((struct sf_buf *)m); -} - -/* - * Free the sf_buf. In fact, do nothing because there are no resources - * associated with the sf_buf. - */ -void -sf_buf_free(struct sf_buf *sf) -{ -} - -/* * Software interrupt handler for queued VM system processing. */ void diff --git a/sys/ia64/include/sf_buf.h b/sys/ia64/include/sf_buf.h index 75bcdfa..44d0109 100644 --- a/sys/ia64/include/sf_buf.h +++ b/sys/ia64/include/sf_buf.h @@ -41,6 +41,18 @@ */ struct sf_buf; +static inline struct sf_buf * +sf_buf_alloc(struct vm_page *m, int pri) +{ + + return ((struct sf_buf *)m); +} + +static inline void +sf_buf_free(struct sf_buf *sf) +{ +} + static __inline vm_page_t sf_buf_page(struct sf_buf *sf) { diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf index d2fa51c..eaa5b14 100644 --- a/sys/kern/capabilities.conf +++ b/sys/kern/capabilities.conf @@ -114,8 +114,7 @@ cap_fcntls_limit cap_getmode cap_ioctls_get cap_ioctls_limit -cap_new -cap_rights_get +__cap_rights_get cap_rights_limit ## diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 0fcb9df..64b0201 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 251526 2013-06-08 13:27:57Z glebius + * created from FreeBSD: head/sys/kern/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #include "opt_compat.h" @@ -548,8 +548,8 @@ struct sysent sysent[] = { { AS(msgctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 511 = msgctl */ { AS(shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 512 = shmctl */ { AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 513 = lpathconf */ - { AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 514 = cap_new */ - { AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 515 = cap_rights_get */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 514 = obsolete cap_new */ + { AS(__cap_rights_get_args), (sy_call_t *)sys___cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 515 = __cap_rights_get */ { 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 516 = cap_enter */ { AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 517 = cap_getmode */ { AS(pdfork_args), (sy_call_t *)sys_pdfork, AUE_PDFORK, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 518 = pdfork */ diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d0de6b9..9e9010f 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -455,6 +455,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) struct filedescent *fde; struct proc *p; struct vnode *vp; + cap_rights_t rights; int error, flg, tmp; u_int old, new; uint64_t bsize; @@ -515,7 +516,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETFL: - error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETFL, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights, CAP_FCNTL), F_GETFL, &fp, NULL); if (error != 0) break; td->td_retval[0] = OFLAGS(fp->f_flag); @@ -523,7 +525,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_SETFL: - error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETFL, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights, CAP_FCNTL), F_SETFL, &fp, NULL); if (error != 0) break; do { @@ -550,7 +553,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETOWN: - error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETOWN, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights, CAP_FCNTL), F_GETOWN, &fp, NULL); if (error != 0) break; error = fo_ioctl(fp, FIOGETOWN, &tmp, td->td_ucred, td); @@ -560,7 +564,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_SETOWN: - error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETOWN, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights, CAP_FCNTL), F_SETOWN, &fp, NULL); if (error != 0) break; tmp = arg; @@ -581,7 +586,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) case F_SETLK: do_setlk: - error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL); + cap_rights_init(&rights, CAP_FLOCK); + error = fget_unlocked(fdp, fd, &rights, 0, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -670,7 +676,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) * that the closing thread was a bit slower and that the * advisory lock succeeded before the close. */ - error = fget_unlocked(fdp, fd, 0, 0, &fp2, NULL); + error = fget_unlocked(fdp, fd, &rights, 0, &fp2, NULL); if (error != 0) { fdrop(fp, td); break; @@ -688,7 +694,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETLK: - error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights, CAP_FLOCK), 0, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -726,7 +733,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) arg = arg ? 128 * 1024: 0; /* FALLTHROUGH */ case F_READAHEAD: - error = fget_unlocked(fdp, fd, 0, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, NULL, 0, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -1281,11 +1288,13 @@ int kern_fstat(struct thread *td, int fd, struct stat *sbp) { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(fd); - if ((error = fget(td, fd, CAP_FSTAT, &fp)) != 0) + error = fget(td, fd, cap_rights_init(&rights, CAP_FSTAT), &fp); + if (error != 0) return (error); AUDIT_ARG_FILE(td->td_proc, fp); @@ -1339,9 +1348,11 @@ sys_fpathconf(struct thread *td, struct fpathconf_args *uap) { struct file *fp; struct vnode *vp; + cap_rights_t rights; int error; - if ((error = fget(td, uap->fd, CAP_FPATHCONF, &fp)) != 0) + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp); + if (error != 0) return (error); /* If asynchronous I/O is available, it works for all descriptors. */ @@ -1417,7 +1428,7 @@ static void filecaps_fill(struct filecaps *fcaps) { - fcaps->fc_rights = CAP_ALL; + CAP_ALL(&fcaps->fc_rights); fcaps->fc_ioctls = NULL; fcaps->fc_nioctls = -1; fcaps->fc_fcntls = CAP_FCNTL_ALL; @@ -1441,16 +1452,18 @@ static void filecaps_validate(const struct filecaps *fcaps, const char *func) { - KASSERT((fcaps->fc_rights & ~CAP_MASK_VALID) == 0, + KASSERT(cap_rights_is_valid(&fcaps->fc_rights), ("%s: invalid rights", func)); KASSERT((fcaps->fc_fcntls & ~CAP_FCNTL_ALL) == 0, ("%s: invalid fcntls", func)); - KASSERT(fcaps->fc_fcntls == 0 || (fcaps->fc_rights & CAP_FCNTL) != 0, + KASSERT(fcaps->fc_fcntls == 0 || + cap_rights_is_set(&fcaps->fc_rights, CAP_FCNTL), ("%s: fcntls without CAP_FCNTL", func)); KASSERT(fcaps->fc_ioctls != NULL ? fcaps->fc_nioctls > 0 : (fcaps->fc_nioctls == -1 || fcaps->fc_nioctls == 0), ("%s: invalid ioctls", func)); - KASSERT(fcaps->fc_nioctls == 0 || (fcaps->fc_rights & CAP_IOCTL) != 0, + KASSERT(fcaps->fc_nioctls == 0 || + cap_rights_is_set(&fcaps->fc_rights, CAP_IOCTL), ("%s: ioctls without CAP_IOCTL", func)); } @@ -2285,7 +2298,7 @@ finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops) } int -fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights, +fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, int needfcntl, struct file **fpp, cap_rights_t *haverightsp) { struct file *fp; @@ -2310,14 +2323,16 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights, if (fp == NULL) return (EBADF); #ifdef CAPABILITIES - haverights = cap_rights(fdp, fd); - error = cap_check(haverights, needrights); - if (error != 0) - return (error); - if ((needrights & CAP_FCNTL) != 0) { - error = cap_fcntl_check(fdp, fd, needfcntl); + haverights = *cap_rights(fdp, fd); + if (needrightsp != NULL) { + error = cap_check(&haverights, needrightsp); if (error != 0) return (error); + if (cap_rights_is_set(needrightsp, CAP_FCNTL)) { + error = cap_fcntl_check(fdp, fd, needfcntl); + if (error != 0) + return (error); + } } #endif count = fp->f_count; @@ -2338,7 +2353,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights, #ifdef CAPABILITIES *haverightsp = haverights; #else - *haverightsp = CAP_ALL; + CAP_ALL(haverightsp); #endif } return (0); @@ -2359,19 +2374,23 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights, */ static __inline int _fget(struct thread *td, int fd, struct file **fpp, int flags, - cap_rights_t needrights, u_char *maxprotp) + cap_rights_t *needrightsp, u_char *maxprotp) { struct filedesc *fdp; struct file *fp; - cap_rights_t haverights; + cap_rights_t haverights, needrights; int error; *fpp = NULL; if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) return (EBADF); + if (needrightsp != NULL) + needrights = *needrightsp; + else + cap_rights_init(&needrights); if (maxprotp != NULL) - needrights |= CAP_MMAP; - error = fget_unlocked(fdp, fd, needrights, 0, &fp, &haverights); + cap_rights_set(&needrights, CAP_MMAP); + error = fget_unlocked(fdp, fd, &needrights, 0, &fp, &haverights); if (error != 0) return (error); if (fp->f_ops == &badfileops) { @@ -2384,7 +2403,7 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, * If requested, convert capability rights to access flags. */ if (maxprotp != NULL) - *maxprotp = cap_rights_to_vmprot(haverights); + *maxprotp = cap_rights_to_vmprot(&haverights); #else /* !CAPABILITIES */ if (maxprotp != NULL) *maxprotp = VM_PROT_ALL; @@ -2421,32 +2440,32 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, } int -fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp) +fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) { - return(_fget(td, fd, fpp, 0, rights, NULL)); + return(_fget(td, fd, fpp, 0, rightsp, NULL)); } int -fget_mmap(struct thread *td, int fd, cap_rights_t rights, u_char *maxprotp, +fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, u_char *maxprotp, struct file **fpp) { - return (_fget(td, fd, fpp, 0, rights, maxprotp)); + return (_fget(td, fd, fpp, 0, rightsp, maxprotp)); } int -fget_read(struct thread *td, int fd, cap_rights_t rights, struct file **fpp) +fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) { - return(_fget(td, fd, fpp, FREAD, rights, NULL)); + return(_fget(td, fd, fpp, FREAD, rightsp, NULL)); } int -fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp) +fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) { - return (_fget(td, fd, fpp, FWRITE, rights, NULL)); + return (_fget(td, fd, fpp, FWRITE, rightsp, NULL)); } /* @@ -2457,15 +2476,15 @@ fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp) * XXX: what about the unused flags ? */ static __inline int -_fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights, +_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, struct vnode **vpp) { struct file *fp; int error; *vpp = NULL; - error = _fget(td, fd, &fp, flags, needrights, NULL); - if (error) + error = _fget(td, fd, &fp, flags, needrightsp, NULL); + if (error != 0) return (error); if (fp->f_vnode == NULL) { error = EINVAL; @@ -2479,14 +2498,14 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights, } int -fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp) +fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) { - return (_fgetvp(td, fd, 0, rights, vpp)); + return (_fgetvp(td, fd, 0, rightsp, vpp)); } int -fgetvp_rights(struct thread *td, int fd, cap_rights_t need, +fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, struct filecaps *havecaps, struct vnode **vpp) { struct filedesc *fdp; @@ -2503,9 +2522,11 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t need, return (EBADF); #ifdef CAPABILITIES - error = cap_check(cap_rights(fdp, fd), need); - if (error != 0) - return (error); + if (needrightsp != NULL) { + error = cap_check(cap_rights(fdp, fd), needrightsp); + if (error != 0) + return (error); + } #endif if (fp->f_vnode == NULL) @@ -2519,26 +2540,26 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t need, } int -fgetvp_read(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp) +fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) { - return (_fgetvp(td, fd, FREAD, rights, vpp)); + return (_fgetvp(td, fd, FREAD, rightsp, vpp)); } int -fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp) +fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) { - return (_fgetvp(td, fd, FEXEC, rights, vpp)); + return (_fgetvp(td, fd, FEXEC, rightsp, vpp)); } #ifdef notyet int -fgetvp_write(struct thread *td, int fd, cap_rights_t rights, +fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp) { - return (_fgetvp(td, fd, FWRITE, rights, vpp)); + return (_fgetvp(td, fd, FWRITE, rightsp, vpp)); } #endif @@ -2554,7 +2575,7 @@ fgetvp_write(struct thread *td, int fd, cap_rights_t rights, * during use. */ int -fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp, +fgetsock(struct thread *td, int fd, cap_rights_t *rightsp, struct socket **spp, u_int *fflagp) { struct file *fp; @@ -2563,7 +2584,7 @@ fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp, *spp = NULL; if (fflagp != NULL) *fflagp = 0; - if ((error = _fget(td, fd, &fp, 0, rights, NULL)) != 0) + if ((error = _fget(td, fd, &fp, 0, rightsp, NULL)) != 0) return (error); if (fp->f_type != DTYPE_SOCKET) { error = ENOTSOCK; @@ -2637,9 +2658,11 @@ sys_flock(struct thread *td, struct flock_args *uap) struct file *fp; struct vnode *vp; struct flock lf; + cap_rights_t rights; int error; - if ((error = fget(td, uap->fd, CAP_FLOCK, &fp)) != 0) + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FLOCK), &fp); + if (error != 0) return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); @@ -3185,7 +3208,7 @@ struct export_fd_buf { static int export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt, - int64_t offset, cap_rights_t fd_cap_rights, struct export_fd_buf *efbuf) + int64_t offset, cap_rights_t *rightsp, struct export_fd_buf *efbuf) { struct { int fflag; @@ -3259,7 +3282,10 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt, for (i = 0; i < NFFLAGS; i++) if (fflags & fflags_table[i].fflag) kif->kf_flags |= fflags_table[i].kf_fflag; - kif->kf_cap_rights = fd_cap_rights; + if (rightsp != NULL) + kif->kf_cap_rights = *rightsp; + else + cap_rights_init(&kif->kf_cap_rights); kif->kf_fd = fd; kif->kf_type = type; kif->kf_ref_count = refcnt; @@ -3302,7 +3328,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) void *data; int error, i; int type, refcnt, fflags; - cap_rights_t fd_cap_rights; + cap_rights_t rights; PROC_LOCK_ASSERT(p, MA_OWNED); @@ -3329,13 +3355,13 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) efbuf->remainder = maxlen; if (tracevp != NULL) export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE, - FREAD | FWRITE, -1, -1, 0, efbuf); + FREAD | FWRITE, -1, -1, NULL, efbuf); if (textvp != NULL) export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT, - FREAD, -1, -1, 0, efbuf); + FREAD, -1, -1, NULL, efbuf); if (cttyvp != NULL) export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY, - FREAD | FWRITE, -1, -1, 0, efbuf); + FREAD | FWRITE, -1, -1, NULL, efbuf); error = 0; if (fdp == NULL) goto fail; @@ -3346,30 +3372,30 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) vref(fdp->fd_cdir); data = fdp->fd_cdir; export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD, - FREAD, -1, -1, 0, efbuf); + FREAD, -1, -1, NULL, efbuf); } /* root directory */ if (fdp->fd_rdir != NULL) { vref(fdp->fd_rdir); data = fdp->fd_rdir; export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT, - FREAD, -1, -1, 0, efbuf); + FREAD, -1, -1, NULL, efbuf); } /* jail directory */ if (fdp->fd_jdir != NULL) { vref(fdp->fd_jdir); data = fdp->fd_jdir; export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL, - FREAD, -1, -1, 0, efbuf); + FREAD, -1, -1, NULL, efbuf); } for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) continue; data = NULL; #ifdef CAPABILITIES - fd_cap_rights = cap_rights(fdp, i); + rights = *cap_rights(fdp, i); #else /* !CAPABILITIES */ - fd_cap_rights = 0; + cap_rights_init(&rights); #endif switch (fp->f_type) { case DTYPE_VNODE: @@ -3443,8 +3469,8 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) * the loop continues. */ error = export_fd_to_sb(data, type, i, fflags, refcnt, - offset, fd_cap_rights, efbuf); - if (error) + offset, &rights, efbuf); + if (error != 0) break; } FILEDESC_SUNLOCK(fdp); diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index dfd1c46..8bde25a 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -824,9 +824,11 @@ kern_kevent(struct thread *td, int fd, int nchanges, int nevents, struct kevent *kevp, *changes; struct kqueue *kq; struct file *fp; + cap_rights_t rights; int i, n, nerrors, error; - if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0) + error = fget(td, fd, cap_rights_init(&rights, CAP_POST_EVENT), &fp); + if (error != 0) return (error); if ((error = kqueue_acquire(fp, &kq)) != 0) goto done_norel; @@ -964,6 +966,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa struct filterops *fops; struct file *fp; struct knote *kn, *tkn; + cap_rights_t rights; int error, filt, event; int haskqglobal; @@ -982,7 +985,8 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa findkn: if (fops->f_isfd) { KASSERT(td != NULL, ("td is NULL")); - error = fget(td, kev->ident, CAP_POLL_EVENT, &fp); + error = fget(td, kev->ident, + cap_rights_init(&rights, CAP_POLL_EVENT), &fp); if (error) goto done; @@ -2237,9 +2241,11 @@ kqfd_register(int fd, struct kevent *kev, struct thread *td, int waitok) { struct kqueue *kq; struct file *fp; + cap_rights_t rights; int error; - if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0) + error = fget(td, fd, cap_rights_init(&rights, CAP_POST_EVENT), &fp); + if (error != 0) return (error); if ((error = kqueue_acquire(fp, &kq)) != 0) goto noacquire; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 833fd18..45f732b 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -338,6 +338,7 @@ do_execve(td, args, mac_p) struct ucred *tracecred = NULL; #endif struct vnode *textvp = NULL, *binvp = NULL; + cap_rights_t rights; int credential_changing; int textset; #ifdef MAC @@ -438,7 +439,8 @@ interpret: /* * Descriptors opened only with O_EXEC or O_RDONLY are allowed. */ - error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp); + error = fgetvp_exec(td, args->fd, + cap_rights_init(&rights, CAP_FEXECVE), &binvp); if (error) goto exec_fail; vn_lock(binvp, LK_EXCLUSIVE | LK_RETRY); diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 6451825..331b0e1 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -3885,6 +3885,13 @@ prison_priv_check(struct ucred *cred, int priv) case PRIV_VFS_SETGID: case PRIV_VFS_STAT: case PRIV_VFS_STICKYFILE: + + /* + * As in the non-jail case, non-root users are expected to be + * able to read kernel/phyiscal memory (provided /dev/[k]mem + * exists in the jail and they have permission to access it). + */ + case PRIV_KMEM_READ: return (0); /* diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index e512a33..3b34fb0 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -779,8 +779,8 @@ ktrstruct(name, data, datalen) void ktrcapfail(type, needed, held) enum ktr_cap_fail_type type; - cap_rights_t needed; - cap_rights_t held; + const cap_rights_t *needed; + const cap_rights_t *held; { struct thread *td = curthread; struct ktr_request *req; @@ -791,8 +791,8 @@ ktrcapfail(type, needed, held) return; kcf = &req->ktr_data.ktr_cap_fail; kcf->cap_type = type; - kcf->cap_needed = needed; - kcf->cap_held = held; + kcf->cap_needed = *needed; + kcf->cap_held = *held; ktr_enqueuerequest(td, req); ktrace_exit(td); } diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 4d45553..5d58942 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -106,7 +106,7 @@ int nmbjumbo16; /* limits number of 16k jumbo clusters */ static quad_t maxmbufmem; /* overall real memory limit for all mbufs */ SYSCTL_QUAD(_kern_ipc, OID_AUTO, maxmbufmem, CTLFLAG_RDTUN, &maxmbufmem, 0, - "Maximum real memory allocateable to various mbuf types"); + "Maximum real memory allocatable to various mbuf types"); /* * tunable_mbinit() has to be run before any mbuf allocations are done. diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 22fc1b7..1797ebc 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1726,6 +1726,7 @@ sys_pdkill(td, uap) { #ifdef PROCDESC struct proc *p; + cap_rights_t rights; int error; AUDIT_ARG_SIGNUM(uap->signum); @@ -1733,7 +1734,8 @@ sys_pdkill(td, uap) if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); - error = procdesc_find(td, uap->fd, CAP_PDKILL, &p); + error = procdesc_find(td, uap->fd, + cap_rights_init(&rights, CAP_PDKILL), &p); if (error) return (error); AUDIT_ARG_PROCESS(p); diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c new file mode 100644 index 0000000..7043fe7 --- /dev/null +++ b/sys/kern/subr_capability.c @@ -0,0 +1,285 @@ +/*- + * Copyright (c) 2013 FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#ifdef _KERNEL +#include <sys/types.h> +#include <sys/capability.h> +#include <sys/systm.h> + +#include <machine/stdarg.h> +#else /* !_KERNEL */ +#include <sys/types.h> +#include <sys/capability.h> + +#include <assert.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#endif + +#ifdef _KERNEL +#define assert(exp) KASSERT((exp), ("%s:%u", __func__, __LINE__)) +#endif + +static __inline unsigned int +right_to_index(uint64_t right) +{ + static const int bit2idx[] = { + -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, + 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + int idx; + + idx = CAPIDXBIT(right); + assert(idx == 1 || idx == 2 || idx == 4 || idx == 8 || idx == 16); + + idx = bit2idx[idx]; + assert(idx >= 0 && idx <= 4); + + return ((unsigned int)idx); +} + +static void +cap_rights_vset(cap_rights_t *rights, va_list ap) +{ + unsigned int i, n; + uint64_t right; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + n = CAPARSIZE(rights); + + for (;;) { + right = (uint64_t)va_arg(ap, unsigned long long); + if (right == 0) + break; + assert(CAPRVER(right) == 0); + i = right_to_index(right); + assert(i < n); + assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); + rights->cr_rights[i] |= right; + assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); + } +} + +static void +cap_rights_vclear(cap_rights_t *rights, va_list ap) +{ + unsigned int i, n; + uint64_t right; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + n = CAPARSIZE(rights); + + for (;;) { + right = (uint64_t)va_arg(ap, unsigned long long); + if (right == 0) + break; + assert(CAPRVER(right) == 0); + i = right_to_index(right); + assert(i < n); + assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); + rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL); + assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); + } +} + +static bool +cap_rights_is_vset(const cap_rights_t *rights, va_list ap) +{ + unsigned int i, n; + uint64_t right; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + n = CAPARSIZE(rights); + + for (;;) { + right = (uint64_t)va_arg(ap, unsigned long long); + if (right == 0) + break; + assert(CAPRVER(right) == 0); + i = right_to_index(right); + assert(i < n); + assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); + if ((rights->cr_rights[i] & right) != right) + return (false); + } + + return (true); +} + +cap_rights_t * +__cap_rights_init(int version, cap_rights_t *rights, ...) +{ + unsigned int n; + va_list ap; + + assert(version == CAP_RIGHTS_VERSION_00); + + n = version + 2; + memset(rights->cr_rights, 0, sizeof(rights->cr_rights[0]) * n); + CAP_NONE(rights); + va_start(ap, rights); + cap_rights_vset(rights, ap); + va_end(ap); + + return (rights); +} + +void +__cap_rights_set(cap_rights_t *rights, ...) +{ + va_list ap; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + va_start(ap, rights); + cap_rights_vset(rights, ap); + va_end(ap); +} + +void +__cap_rights_clear(cap_rights_t *rights, ...) +{ + va_list ap; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + va_start(ap, rights); + cap_rights_vclear(rights, ap); + va_end(ap); +} + +bool +__cap_rights_is_set(const cap_rights_t *rights, ...) +{ + va_list ap; + bool ret; + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + + va_start(ap, rights); + ret = cap_rights_is_vset(rights, ap); + va_end(ap); + + return (ret); +} + +bool +cap_rights_is_valid(const cap_rights_t *rights) +{ + cap_rights_t allrights; + unsigned int i, j; + + if (CAPVER(rights) != CAP_RIGHTS_VERSION_00) + return (false); + CAP_ALL(&allrights); + if (!cap_rights_contains(&allrights, rights)) + return (false); + for (i = 0; i < CAPARSIZE(rights); i++) { + j = right_to_index(rights->cr_rights[i]); + if (i != j) + return (false); + if (i > 0) { + if (CAPRVER(rights->cr_rights[i]) != 0) + return (false); + } + } + + return (true); +} + +void +cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src) +{ + unsigned int i, n; + + assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(dst) == CAPVER(src)); + assert(cap_rights_is_valid(src)); + assert(cap_rights_is_valid(dst)); + + n = CAPARSIZE(dst); + + for (i = 0; i < n; i++) + dst->cr_rights[i] |= src->cr_rights[i]; + + assert(cap_rights_is_valid(src)); + assert(cap_rights_is_valid(dst)); +} + +void +cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src) +{ + unsigned int i, n; + + assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(dst) == CAPVER(src)); + assert(cap_rights_is_valid(src)); + assert(cap_rights_is_valid(dst)); + + n = CAPARSIZE(dst); + + for (i = 0; i < n; i++) { + dst->cr_rights[i] &= + ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL); + } + + assert(cap_rights_is_valid(src)); + assert(cap_rights_is_valid(dst)); +} + +bool +cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) +{ + unsigned int i, n; + + assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(big) == CAPVER(little)); + + n = CAPARSIZE(big); + + for (i = 0; i < n; i++) { + if ((big->cr_rights[i] & little->cr_rights[i]) != + little->cr_rights[i]) { + return (false); + } + } + + return (true); +} diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 37e8cf2..9d3040d 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -1138,18 +1138,12 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file, iclass = LOCK_CLASS(interlock); lock1 = find_instance(lock_list, interlock); if (lock1 == NULL) - kassert_panic( - "interlock (%s) %s not locked while locking" - " %s @ %s:%d", + kassert_panic("interlock (%s) %s not locked @ %s:%d", iclass->lc_name, interlock->lo_name, - flags & LOP_EXCLUSIVE ? "exclusive" : "shared", fixup_filename(file), line); else if ((lock1->li_flags & LI_RECURSEMASK) != 0) - kassert_panic( - "interlock (%s) %s recursed while locking %s" - " @ %s:%d", + kassert_panic("interlock (%s) %s recursed @ %s:%d", iclass->lc_name, interlock->lo_name, - flags & LOP_EXCLUSIVE ? "exclusive" : "shared", fixup_filename(file), line); } diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index 224042e..7a82017 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -148,16 +148,19 @@ FEATURE(security_capabilities, "Capsicum Capabilities"); MALLOC_DECLARE(M_FILECAPS); static inline int -_cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type) +_cap_check(const cap_rights_t *havep, const cap_rights_t *needp, + enum ktr_cap_fail_type type) { + int i; - - if ((need & ~have) != 0) { + for (i = 0; i < nitems(havep->cr_rights); i++) { + if (!cap_rights_contains(havep, needp)) { #ifdef KTRACE - if (KTRPOINT(curthread, KTR_CAPFAIL)) - ktrcapfail(type, need, have); + if (KTRPOINT(curthread, KTR_CAPFAIL)) + ktrcapfail(type, needp, havep); #endif - return (ENOTCAPABLE); + return (ENOTCAPABLE); + } } return (0); } @@ -166,26 +169,26 @@ _cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type) * Test whether a capability grants the requested rights. */ int -cap_check(cap_rights_t have, cap_rights_t need) +cap_check(const cap_rights_t *havep, const cap_rights_t *needp) { - return (_cap_check(have, need, CAPFAIL_NOTCAPABLE)); + return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE)); } /* * Convert capability rights into VM access flags. */ u_char -cap_rights_to_vmprot(cap_rights_t have) +cap_rights_to_vmprot(cap_rights_t *havep) { u_char maxprot; maxprot = VM_PROT_NONE; - if (have & CAP_MMAP_R) + if (cap_rights_is_set(havep, CAP_MMAP_R)) maxprot |= VM_PROT_READ; - if (have & CAP_MMAP_W) + if (cap_rights_is_set(havep, CAP_MMAP_W)) maxprot |= VM_PROT_WRITE; - if (have & CAP_MMAP_X) + if (cap_rights_is_set(havep, CAP_MMAP_X)) maxprot |= VM_PROT_EXECUTE; return (maxprot); @@ -196,11 +199,11 @@ cap_rights_to_vmprot(cap_rights_t have) * any other way, as we want to keep all capability permission evaluation in * this one file. */ -cap_rights_t +cap_rights_t * cap_rights(struct filedesc *fdp, int fd) { - return (fdp->fd_ofiles[fd].fde_rights); + return (&fdp->fd_ofiles[fd].fde_rights); } /* @@ -211,32 +214,57 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap) { struct filedesc *fdp; cap_rights_t rights; - int error, fd; + int error, fd, version; - fd = uap->fd; - rights = uap->rights; + cap_rights_init(&rights); - AUDIT_ARG_FD(fd); - AUDIT_ARG_RIGHTS(rights); + error = copyin(uap->rightsp, &rights, sizeof(rights.cr_rights[0])); + if (error != 0) + return (error); + version = CAPVER(&rights); + if (version != CAP_RIGHTS_VERSION_00) + return (EINVAL); - if ((rights & ~CAP_ALL) != 0) + error = copyin(uap->rightsp, &rights, + sizeof(rights.cr_rights[0]) * CAPARSIZE(&rights)); + if (error != 0) + return (error); + /* Check for race. */ + if (CAPVER(&rights) != version) return (EINVAL); + if (!cap_rights_is_valid(&rights)) + return (EINVAL); + + if (version != CAP_RIGHTS_VERSION) { + rights.cr_rights[0] &= ~(0x3ULL << 62); + rights.cr_rights[0] |= ((uint64_t)CAP_RIGHTS_VERSION << 62); + } +#ifdef KTRACE + if (KTRPOINT(td, KTR_STRUCT)) + ktrcaprights(&rights); +#endif + + fd = uap->fd; + + AUDIT_ARG_FD(fd); + AUDIT_ARG_RIGHTS(&rights); + fdp = td->td_proc->p_fd; FILEDESC_XLOCK(fdp); if (fget_locked(fdp, fd) == NULL) { FILEDESC_XUNLOCK(fdp); return (EBADF); } - error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE); + error = _cap_check(cap_rights(fdp, fd), &rights, CAPFAIL_INCREASE); if (error == 0) { fdp->fd_ofiles[fd].fde_rights = rights; - if ((rights & CAP_IOCTL) == 0) { + if (!cap_rights_is_set(&rights, CAP_IOCTL)) { free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS); fdp->fd_ofiles[fd].fde_ioctls = NULL; fdp->fd_ofiles[fd].fde_nioctls = 0; } - if ((rights & CAP_FCNTL) == 0) + if (!cap_rights_is_set(&rights, CAP_FCNTL)) fdp->fd_ofiles[fd].fde_fcntls = 0; } FILEDESC_XUNLOCK(fdp); @@ -247,11 +275,14 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap) * System call to query the rights mask associated with a capability. */ int -sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap) +sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap) { struct filedesc *fdp; cap_rights_t rights; - int fd; + int error, fd, i, n; + + if (uap->version != CAP_RIGHTS_VERSION_00) + return (EINVAL); fd = uap->fd; @@ -263,9 +294,26 @@ sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap) FILEDESC_SUNLOCK(fdp); return (EBADF); } - rights = cap_rights(fdp, fd); + rights = *cap_rights(fdp, fd); FILEDESC_SUNLOCK(fdp); - return (copyout(&rights, uap->rightsp, sizeof(*uap->rightsp))); + n = uap->version + 2; + if (uap->version != CAPVER(&rights)) { + /* + * For older versions we need to check if the descriptor + * doesn't contain rights not understood by the caller. + * If it does, we have to return an error. + */ + for (i = n; i < CAPARSIZE(&rights); i++) { + if ((rights.cr_rights[i] & ~(0x7FULL << 57)) != 0) + return (EINVAL); + } + } + error = copyout(&rights, uap->rightsp, sizeof(rights.cr_rights[0]) * n); +#ifdef KTRACE + if (error == 0 && KTRPOINT(td, KTR_STRUCT)) + ktrcaprights(&rights); +#endif + return (error); } /* @@ -513,65 +561,6 @@ sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap) return (copyout(&rights, uap->fcntlrightsp, sizeof(rights))); } -/* - * For backward compatibility. - */ -int -sys_cap_new(struct thread *td, struct cap_new_args *uap) -{ - struct filedesc *fdp; - cap_rights_t rights; - register_t newfd; - int error, fd; - - fd = uap->fd; - rights = uap->rights; - - AUDIT_ARG_FD(fd); - AUDIT_ARG_RIGHTS(rights); - - if ((rights & ~CAP_ALL) != 0) - return (EINVAL); - - fdp = td->td_proc->p_fd; - FILEDESC_SLOCK(fdp); - if (fget_locked(fdp, fd) == NULL) { - FILEDESC_SUNLOCK(fdp); - return (EBADF); - } - error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE); - FILEDESC_SUNLOCK(fdp); - if (error != 0) - return (error); - - error = do_dup(td, 0, fd, 0, &newfd); - if (error != 0) - return (error); - - FILEDESC_XLOCK(fdp); - /* - * We don't really care about the race between checking capability - * rights for the source descriptor and now. If capability rights - * were ok at that earlier point, the process had this descriptor - * with those rights, so we don't increase them in security sense, - * the process might have done the cap_new(2) a bit earlier to get - * the same effect. - */ - fdp->fd_ofiles[newfd].fde_rights = rights; - if ((rights & CAP_IOCTL) == 0) { - free(fdp->fd_ofiles[newfd].fde_ioctls, M_FILECAPS); - fdp->fd_ofiles[newfd].fde_ioctls = NULL; - fdp->fd_ofiles[newfd].fde_nioctls = 0; - } - if ((rights & CAP_FCNTL) == 0) - fdp->fd_ofiles[newfd].fde_fcntls = 0; - FILEDESC_XUNLOCK(fdp); - - td->td_retval[0] = newfd; - - return (0); -} - #else /* !CAPABILITIES */ /* @@ -587,7 +576,7 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap) } int -sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap) +sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap) { return (ENOSYS); @@ -621,11 +610,4 @@ sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap) return (ENOSYS); } -int -sys_cap_new(struct thread *td, struct cap_new_args *uap) -{ - - return (ENOSYS); -} - #endif /* CAPABILITIES */ diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 44d1a89..d4d6293 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -243,9 +243,10 @@ int kern_readv(struct thread *td, int fd, struct uio *auio) { struct file *fp; + cap_rights_t rights; int error; - error = fget_read(td, fd, CAP_READ, &fp); + error = fget_read(td, fd, cap_rights_init(&rights, CAP_READ), &fp); if (error) return (error); error = dofileread(td, fd, fp, auio, (off_t)-1, 0); @@ -286,9 +287,10 @@ kern_preadv(td, fd, auio, offset) off_t offset; { struct file *fp; + cap_rights_t rights; int error; - error = fget_read(td, fd, CAP_PREAD, &fp); + error = fget_read(td, fd, cap_rights_init(&rights, CAP_PREAD), &fp); if (error) return (error); if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) @@ -452,9 +454,10 @@ int kern_writev(struct thread *td, int fd, struct uio *auio) { struct file *fp; + cap_rights_t rights; int error; - error = fget_write(td, fd, CAP_WRITE, &fp); + error = fget_write(td, fd, cap_rights_init(&rights, CAP_WRITE), &fp); if (error) return (error); error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0); @@ -495,9 +498,10 @@ kern_pwritev(td, fd, auio, offset) off_t offset; { struct file *fp; + cap_rights_t rights; int error; - error = fget_write(td, fd, CAP_PWRITE, &fp); + error = fget_write(td, fd, cap_rights_init(&rights, CAP_PWRITE), &fp); if (error) return (error); if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) @@ -575,12 +579,13 @@ kern_ftruncate(td, fd, length) off_t length; { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(fd); if (length < 0) return (EINVAL); - error = fget(td, fd, CAP_FTRUNCATE, &fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp); if (error) return (error); AUDIT_ARG_FILE(td->td_proc, fp); @@ -705,6 +710,9 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data) { struct file *fp; struct filedesc *fdp; +#ifndef CAPABILITIES + cap_rights_t rights; +#endif int error, tmp, locked; AUDIT_ARG_FD(fd); @@ -743,7 +751,8 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data) locked = LA_UNLOCKED; } #else - if ((error = fget(td, fd, CAP_IOCTL, &fp)) != 0) { + error = fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) { fp = NULL; goto out; } @@ -1180,8 +1189,10 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events) static __inline int getselfd_cap(struct filedesc *fdp, int fd, struct file **fpp) { + cap_rights_t rights; - return (fget_unlocked(fdp, fd, CAP_POLL_EVENT, 0, fpp, NULL)); + return (fget_unlocked(fdp, fd, cap_rights_init(&rights, CAP_POLL_EVENT), + 0, fpp, NULL)); } /* @@ -1357,6 +1368,9 @@ pollrescan(struct thread *td) struct filedesc *fdp; struct file *fp; struct pollfd *fd; +#ifdef CAPABILITIES + cap_rights_t rights; +#endif int n; n = 0; @@ -1373,7 +1387,8 @@ pollrescan(struct thread *td) fp = fdp->fd_ofiles[fd->fd].fde_file; #ifdef CAPABILITIES if (fp == NULL || - cap_check(cap_rights(fdp, fd->fd), CAP_POLL_EVENT) != 0) + cap_check(cap_rights(fdp, fd->fd), + cap_rights_init(&rights, CAP_POLL_EVENT)) != 0) #else if (fp == NULL) #endif @@ -1431,6 +1446,9 @@ pollscan(td, fds, nfd) { struct filedesc *fdp = td->td_proc->p_fd; struct file *fp; +#ifdef CAPABILITIES + cap_rights_t rights; +#endif int i, n = 0; FILEDESC_SLOCK(fdp); @@ -1445,7 +1463,7 @@ pollscan(td, fds, nfd) #ifdef CAPABILITIES if (fp == NULL || cap_check(cap_rights(fdp, fds->fd), - CAP_POLL_EVENT) != 0) + cap_rights_init(&rights, CAP_POLL_EVENT)) != 0) #else if (fp == NULL) #endif diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index bacaf18..4bafeab 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -138,14 +138,14 @@ SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL); * died. */ int -procdesc_find(struct thread *td, int fd, cap_rights_t rights, +procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp, struct proc **p) { struct procdesc *pd; struct file *fp; int error; - error = fget(td, fd, rights, &fp); + error = fget(td, fd, rightsp, &fp); if (error) return (error); if (fp->f_type != DTYPE_PROCDESC) { @@ -185,12 +185,12 @@ procdesc_pid(struct file *fp_procdesc) * Retrieve the PID associated with a process descriptor. */ int -kern_pdgetpid(struct thread *td, int fd, cap_rights_t rights, pid_t *pidp) +kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp) { struct file *fp; int error; - error = fget(td, fd, rights, &fp); + error = fget(td, fd, rightsp, &fp); if (error) return (error); if (fp->f_type != DTYPE_PROCDESC) { @@ -209,11 +209,13 @@ out: int sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap) { + cap_rights_t rights; pid_t pid; int error; AUDIT_ARG_FD(uap->fd); - error = kern_pdgetpid(td, uap->fd, CAP_PDGETPID, &pid); + error = kern_pdgetpid(td, uap->fd, + cap_rights_init(&rights, CAP_PDGETPID), &pid); if (error == 0) error = copyout(&pid, uap->pidp, sizeof(pid)); return (error); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 17f5448..f330879 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 251526 2013-06-08 13:27:57Z glebius + * created from FreeBSD: head/sys/kern/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ const char *syscallnames[] = { @@ -521,8 +521,8 @@ const char *syscallnames[] = { "msgctl", /* 511 = msgctl */ "shmctl", /* 512 = shmctl */ "lpathconf", /* 513 = lpathconf */ - "cap_new", /* 514 = cap_new */ - "cap_rights_get", /* 515 = cap_rights_get */ + "obs_cap_new", /* 514 = obsolete cap_new */ + "__cap_rights_get", /* 515 = __cap_rights_get */ "cap_enter", /* 516 = cap_enter */ "cap_getmode", /* 517 = cap_getmode */ "pdfork", /* 518 = pdfork */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 789f95a5..e19e310 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -917,9 +917,9 @@ 512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } 513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); } -514 AUE_CAP_NEW STD { int cap_new(int fd, uint64_t rights); } -515 AUE_CAP_RIGHTS_GET STD { int cap_rights_get(int fd, \ - uint64_t *rightsp); } +514 AUE_NULL OBSOL cap_new +515 AUE_CAP_RIGHTS_GET STD { int __cap_rights_get(int version, \ + int fd, cap_rights_t *rightsp); } 516 AUE_CAP_ENTER STD { int cap_enter(void); } 517 AUE_CAP_GETMODE STD { int cap_getmode(u_int *modep); } 518 AUE_PDFORK STD { int pdfork(int *fdp, int flags); } @@ -957,7 +957,7 @@ struct __wrusage *wrusage, \ siginfo_t *info); } 533 AUE_CAP_RIGHTS_LIMIT STD { int cap_rights_limit(int fd, \ - uint64_t rights); } + cap_rights_t *rightsp); } 534 AUE_CAP_IOCTLS_LIMIT STD { int cap_ioctls_limit(int fd, \ const u_long *cmds, size_t ncmds); } 535 AUE_CAP_IOCTLS_GET STD { ssize_t cap_ioctls_get(int fd, \ diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index 59e046b..0a6bae4 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -3126,20 +3126,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 2; break; } - /* cap_new */ - case 514: { - struct cap_new_args *p = params; - iarg[0] = p->fd; /* int */ - uarg[1] = p->rights; /* uint64_t */ - *n_args = 2; - break; - } - /* cap_rights_get */ + /* __cap_rights_get */ case 515: { - struct cap_rights_get_args *p = params; - iarg[0] = p->fd; /* int */ - uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */ - *n_args = 2; + struct __cap_rights_get_args *p = params; + iarg[0] = p->version; /* int */ + iarg[1] = p->fd; /* int */ + uarg[2] = (intptr_t) p->rightsp; /* cap_rights_t * */ + *n_args = 3; break; } /* cap_enter */ @@ -3290,7 +3283,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) case 533: { struct cap_rights_limit_args *p = params; iarg[0] = p->fd; /* int */ - uarg[1] = p->rights; /* uint64_t */ + uarg[1] = (intptr_t) p->rightsp; /* cap_rights_t * */ *n_args = 2; break; } @@ -8561,27 +8554,17 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; - /* cap_new */ - case 514: + /* __cap_rights_get */ + case 515: switch(ndx) { case 0: p = "int"; break; case 1: - p = "uint64_t"; - break; - default: - break; - }; - break; - /* cap_rights_get */ - case 515: - switch(ndx) { - case 0: p = "int"; break; - case 1: - p = "uint64_t *"; + case 2: + p = "cap_rights_t *"; break; default: break; @@ -8849,7 +8832,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) p = "int"; break; case 1: - p = "uint64_t"; + p = "cap_rights_t *"; break; default: break; @@ -10818,12 +10801,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; - /* cap_new */ - case 514: - if (ndx == 0 || ndx == 1) - p = "int"; - break; - /* cap_rights_get */ + /* __cap_rights_get */ case 515: if (ndx == 0 || ndx == 1) p = "int"; diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 02eccd7..4fce607 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1837,11 +1837,13 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd, struct cdev *dev; struct cdevsw *cdp; struct filedesc *fdp; + cap_rights_t rights; int error, ref; /* Validate the file descriptor. */ fdp = p->p_fd; - error = fget_unlocked(fdp, fd, CAP_TTYHOOK, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, cap_rights_init(&rights, CAP_TTYHOOK), + 0, &fp, NULL); if (error != 0) return (error); if (fp->f_ops == &badfileops) { diff --git a/sys/kern/uipc_debug.c b/sys/kern/uipc_debug.c index 57f4017..128c64b 100644 --- a/sys/kern/uipc_debug.c +++ b/sys/kern/uipc_debug.c @@ -411,7 +411,7 @@ db_print_sockbuf(struct sockbuf *sb, const char *sockbufname, int indent) db_print_indent(indent); db_printf("sb_ctl: %u ", sb->sb_ctl); db_printf("sb_lowat: %d ", sb->sb_lowat); - db_printf("sb_timeo: %d\n", sb->sb_timeo); + db_printf("sb_timeo: %jd\n", sb->sb_timeo); db_print_indent(indent); db_printf("sb_flags: 0x%x (", sb->sb_flags); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 62c54d3..fe7e886 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2086,19 +2086,19 @@ sys_kmq_unlink(struct thread *td, struct kmq_unlink_args *uap) return (error); } -typedef int (*_fgetf)(struct thread *, int, cap_rights_t, struct file **); +typedef int (*_fgetf)(struct thread *, int, cap_rights_t *, struct file **); /* * Get message queue by giving file slot */ static int -_getmq(struct thread *td, int fd, cap_rights_t rights, _fgetf func, +_getmq(struct thread *td, int fd, cap_rights_t *rightsp, _fgetf func, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { struct mqfs_node *pn; int error; - error = func(td, fd, rights, fpp); + error = func(td, fd, rightsp, fpp); if (error) return (error); if (&mqueueops != (*fpp)->f_ops) { @@ -2117,21 +2117,30 @@ static __inline int getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - return _getmq(td, fd, CAP_POLL_EVENT, fget, fpp, ppn, pmq); + cap_rights_t rights; + + return _getmq(td, fd, cap_rights_init(&rights, CAP_POLL_EVENT), fget, + fpp, ppn, pmq); } static __inline int getmq_read(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - return _getmq(td, fd, CAP_READ, fget_read, fpp, ppn, pmq); + cap_rights_t rights; + + return _getmq(td, fd, cap_rights_init(&rights, CAP_READ), fget_read, + fpp, ppn, pmq); } static __inline int getmq_write(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - return _getmq(td, fd, CAP_WRITE, fget_write, fpp, ppn, pmq); + cap_rights_t rights; + + return _getmq(td, fd, cap_rights_init(&rights, CAP_WRITE), fget_write, + fpp, ppn, pmq); } static int @@ -2238,6 +2247,9 @@ sys_kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap) static int kern_kmq_notify(struct thread *td, int mqd, struct sigevent *sigev) { +#ifdef CAPABILITIES + cap_rights_t rights; +#endif struct filedesc *fdp; struct proc *p; struct mqueue *mq; @@ -2269,7 +2281,8 @@ again: goto out; } #ifdef CAPABILITIES - error = cap_check(cap_rights(fdp, mqd), CAP_POLL_EVENT); + error = cap_check(cap_rights(fdp, mqd), + cap_rights_init(&rights, CAP_POLL_EVENT)); if (error) { FILEDESC_SUNLOCK(fdp); goto out; diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 8c86cc4..f641654 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -116,7 +116,7 @@ static int ksem_create(struct thread *td, const char *path, semid_t *semidp, mode_t mode, unsigned int value, int flags, int compat32); static void ksem_drop(struct ksem *ks); -static int ksem_get(struct thread *td, semid_t id, cap_rights_t rights, +static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, struct file **fpp); static struct ksem *ksem_hold(struct ksem *ks); static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks); @@ -600,13 +600,14 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, } static int -ksem_get(struct thread *td, semid_t id, cap_rights_t rights, struct file **fpp) +ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, + struct file **fpp) { struct ksem *ks; struct file *fp; int error; - error = fget(td, id, rights, &fp); + error = fget(td, id, rightsp, &fp); if (error) return (EINVAL); if (fp->f_type != DTYPE_SEM) { @@ -720,11 +721,13 @@ struct ksem_post_args { int sys_ksem_post(struct thread *td, struct ksem_post_args *uap) { + cap_rights_t rights; struct file *fp; struct ksem *ks; int error; - error = ksem_get(td, uap->id, CAP_SEM_POST, &fp); + error = ksem_get(td, uap->id, + cap_rights_init(&rights, CAP_SEM_POST), &fp); if (error) return (error); ks = fp->f_data; @@ -809,12 +812,13 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag, { struct timespec ts1, ts2; struct timeval tv; + cap_rights_t rights; struct file *fp; struct ksem *ks; int error; DP((">>> kern_sem_wait entered! pid=%d\n", (int)td->td_proc->p_pid)); - error = ksem_get(td, id, CAP_SEM_WAIT, &fp); + error = ksem_get(td, id, cap_rights_init(&rights, CAP_SEM_WAIT), &fp); if (error) return (error); ks = fp->f_data; @@ -876,11 +880,13 @@ struct ksem_getvalue_args { int sys_ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap) { + cap_rights_t rights; struct file *fp; struct ksem *ks; int error, val; - error = ksem_get(td, uap->id, CAP_SEM_GETVALUE, &fp); + error = ksem_get(td, uap->id, + cap_rights_init(&rights, CAP_SEM_GETVALUE), &fp); if (error) return (error); ks = fp->f_data; diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index a09dbc6..9fa8ae0 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -127,9 +127,9 @@ sbwait(struct sockbuf *sb) SOCKBUF_LOCK_ASSERT(sb); sb->sb_flags |= SB_WAIT; - return (msleep(&sb->sb_cc, &sb->sb_mtx, + return (msleep_sbt(&sb->sb_cc, &sb->sb_mtx, (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", - sb->sb_timeo)); + sb->sb_timeo, 0, 0)); } int diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 75fd04b..639d865 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2541,7 +2541,7 @@ sosetopt(struct socket *so, struct sockopt *sopt) int error, optval; struct linger l; struct timeval tv; - u_long val; + sbintime_t val; uint32_t val32; #ifdef MAC struct mac extmac; @@ -2703,7 +2703,7 @@ sosetopt(struct socket *so, struct sockopt *sopt) error = EDOM; goto bad; } - val = tvtohz(&tv); + val = tvtosbt(tv); switch (sopt->sopt_name) { case SO_SNDTIMEO: @@ -2857,8 +2857,7 @@ integer: optval = (sopt->sopt_name == SO_SNDTIMEO ? so->so_snd.sb_timeo : so->so_rcv.sb_timeo); - tv.tv_sec = optval / hz; - tv.tv_usec = (optval % hz) * tick; + tv = sbttotv(optval); #ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) { struct timeval32 tv32; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 72663a2..8229390 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -164,13 +164,13 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQUE | CTLFLAG_RW, * A reference on the file entry is held upon returning. */ static int -getsock_cap(struct filedesc *fdp, int fd, cap_rights_t rights, +getsock_cap(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp, u_int *fflagp) { struct file *fp; int error; - error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, rightsp, 0, &fp, NULL); if (error != 0) return (error); if (fp->f_type != DTYPE_SOCKET) { @@ -220,16 +220,16 @@ sys_socket(td, uap) #ifdef MAC error = mac_socket_check_create(td->td_ucred, uap->domain, type, uap->protocol); - if (error) + if (error != 0) return (error); #endif error = falloc(td, &fp, &fd, oflag); - if (error) + if (error != 0) return (error); /* An extra reference on `fp' has been held for us by falloc(). */ error = socreate(uap->domain, &so, type, uap->protocol, td->td_ucred, td); - if (error) { + if (error != 0) { fdclose(td->td_proc->p_fd, fp, fd, td); } else { finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops); @@ -267,12 +267,14 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); - error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_BIND), &fp, NULL); + if (error != 0) return (error); so = fp->f_data; #ifdef KTRACE @@ -334,10 +336,12 @@ sys_listen(td, uap) { struct socket *so; struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->s); - error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_LISTEN, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, uap->s, + cap_rights_init(&rights, CAP_LISTEN), &fp, NULL); if (error == 0) { so = fp->f_data; #ifdef MAC @@ -370,7 +374,7 @@ accept1(td, s, uname, anamelen, flags) return (kern_accept4(td, s, NULL, NULL, flags, NULL)); error = copyin(anamelen, &namelen, sizeof (namelen)); - if (error) + if (error != 0) return (error); error = kern_accept4(td, s, &name, &namelen, flags, &fp); @@ -379,7 +383,7 @@ accept1(td, s, uname, anamelen, flags) * return a namelen of zero for older code which might * ignore the return value from accept. */ - if (error) { + if (error != 0) { (void) copyout(&namelen, anamelen, sizeof(*anamelen)); return (error); } @@ -395,7 +399,7 @@ accept1(td, s, uname, anamelen, flags) if (error == 0) error = copyout(&namelen, anamelen, sizeof(namelen)); - if (error) + if (error != 0) fdclose(td->td_proc->p_fd, fp, td->td_retval[0], td); fdrop(fp, td); free(name, M_SONAME); @@ -416,20 +420,20 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, struct filedesc *fdp; struct file *headfp, *nfp = NULL; struct sockaddr *sa = NULL; - int error; struct socket *head, *so; - int fd; + cap_rights_t rights; u_int fflag; pid_t pgid; - int tmp; + int error, fd, tmp; - if (name) + if (name != NULL) *name = NULL; AUDIT_ARG_FD(s); fdp = td->td_proc->p_fd; - error = getsock_cap(fdp, s, CAP_ACCEPT, &headfp, &fflag); - if (error) + error = getsock_cap(fdp, s, cap_rights_init(&rights, CAP_ACCEPT), + &headfp, &fflag); + if (error != 0) return (error); head = headfp->f_data; if ((head->so_options & SO_ACCEPTCONN) == 0) { @@ -442,7 +446,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, goto done; #endif error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0); - if (error) + if (error != 0) goto done; ACCEPT_LOCK(); if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { @@ -457,7 +461,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, } error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH, "accept", 0); - if (error) { + if (error != 0) { ACCEPT_UNLOCK(); goto noconnection; } @@ -516,7 +520,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td); sa = 0; error = soaccept(so, &sa); - if (error) { + if (error != 0) { /* * return a namelen of zero for older code which might * ignore the return value from accept. @@ -543,14 +547,13 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, sa = NULL; } noconnection: - if (sa) - free(sa, M_SONAME); + free(sa, M_SONAME); /* * close the new descriptor, assuming someone hasn't ripped it * out from under us. */ - if (error) + if (error != 0) fdclose(fdp, nfp, fd, td); /* @@ -585,6 +588,7 @@ sys_accept4(td, uap) struct thread *td; struct accept4_args *uap; { + if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) return (EINVAL); @@ -629,13 +633,14 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; - int error; - int interrupted = 0; + cap_rights_t rights; + int error, interrupted = 0; AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); - error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_CONNECT), &fp, NULL); + if (error != 0) return (error); so = fp->f_data; if (so->so_state & SS_ISCONNECTING) { @@ -648,14 +653,14 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) #endif #ifdef MAC error = mac_socket_check_connect(td->td_ucred, so, sa); - if (error) + if (error != 0) goto bad; #endif if (dirfd == AT_FDCWD) error = soconnect(so, sa, td); else error = soconnectat(dirfd, so, sa, td); - if (error) + if (error != 0) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { error = EINPROGRESS; @@ -665,7 +670,7 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH, "connec", 0); - if (error) { + if (error != 0) { if (error == EINTR || error == ERESTART) interrupted = 1; break; @@ -740,35 +745,35 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, /* We might want to have a separate check for socket pairs. */ error = mac_socket_check_create(td->td_ucred, domain, type, protocol); - if (error) + if (error != 0) return (error); #endif error = socreate(domain, &so1, type, protocol, td->td_ucred, td); - if (error) + if (error != 0) return (error); error = socreate(domain, &so2, type, protocol, td->td_ucred, td); - if (error) + if (error != 0) goto free1; /* On success extra reference to `fp1' and 'fp2' is set by falloc. */ error = falloc(td, &fp1, &fd, oflag); - if (error) + if (error != 0) goto free2; rsv[0] = fd; fp1->f_data = so1; /* so1 already has ref count */ error = falloc(td, &fp2, &fd, oflag); - if (error) + if (error != 0) goto free3; fp2->f_data = so2; /* so2 already has ref count */ rsv[1] = fd; error = soconnect2(so1, so2); - if (error) + if (error != 0) goto free4; if (type == SOCK_DGRAM) { /* * Datagram socket connection is asymmetric. */ error = soconnect2(so2, so1); - if (error) + if (error != 0) goto free4; } finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data, @@ -804,10 +809,10 @@ sys_socketpair(struct thread *td, struct socketpair_args *uap) error = kern_socketpair(td, uap->domain, uap->type, uap->protocol, sv); - if (error) + if (error != 0) return (error); error = copyout(sv, uap->rsv, 2 * sizeof(int)); - if (error) { + if (error != 0) { (void)kern_close(td, sv[0]); (void)kern_close(td, sv[1]); } @@ -832,7 +837,7 @@ sendit(td, s, mp, flags) if (mp->msg_name != NULL) { error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); - if (error) { + if (error != 0) { to = NULL; goto bad; } @@ -852,7 +857,7 @@ sendit(td, s, mp, flags) } error = sockargs(&control, mp->msg_control, mp->msg_controllen, MT_CONTROL); - if (error) + if (error != 0) goto bad; #ifdef COMPAT_OLDSOCK if (mp->msg_flags == MSG_COMPAT) { @@ -872,8 +877,7 @@ sendit(td, s, mp, flags) error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE); bad: - if (to) - free(to, M_SONAME); + free(to, M_SONAME); return (error); } @@ -890,21 +894,21 @@ kern_sendit(td, s, mp, flags, control, segflg) struct uio auio; struct iovec *iov; struct socket *so; - int i, error; - ssize_t len; cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif + ssize_t len; + int i, error; AUDIT_ARG_FD(s); - rights = CAP_SEND; + cap_rights_init(&rights, CAP_SEND); if (mp->msg_name != NULL) { AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); - rights |= CAP_CONNECT; + cap_rights_set(&rights, CAP_CONNECT); } - error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, s, &rights, &fp, NULL); + if (error != 0) return (error); so = (struct socket *)fp->f_data; @@ -916,11 +920,11 @@ kern_sendit(td, s, mp, flags, control, segflg) if (mp->msg_name != NULL) { error = mac_socket_check_connect(td->td_ucred, so, mp->msg_name); - if (error) + if (error != 0) goto bad; } error = mac_socket_check_send(td->td_ucred, so); - if (error) + if (error != 0) goto bad; #endif @@ -944,7 +948,7 @@ kern_sendit(td, s, mp, flags, control, segflg) #endif len = auio.uio_resid; error = sosend(so, mp->msg_name, &auio, 0, control, flags, td); - if (error) { + if (error != 0) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -983,7 +987,6 @@ sys_sendto(td, uap) { struct msghdr msg; struct iovec aiov; - int error; msg.msg_name = uap->to; msg.msg_namelen = uap->tolen; @@ -995,8 +998,7 @@ sys_sendto(td, uap) #endif aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - error = sendit(td, uap->s, &msg, uap->flags); - return (error); + return (sendit(td, uap->s, &msg, uap->flags)); } #ifdef COMPAT_OLDSOCK @@ -1012,7 +1014,6 @@ osend(td, uap) { struct msghdr msg; struct iovec aiov; - int error; msg.msg_name = 0; msg.msg_namelen = 0; @@ -1022,8 +1023,7 @@ osend(td, uap) aiov.iov_len = uap->len; msg.msg_control = 0; msg.msg_flags = 0; - error = sendit(td, uap->s, &msg, uap->flags); - return (error); + return (sendit(td, uap->s, &msg, uap->flags)); } int @@ -1040,10 +1040,10 @@ osendmsg(td, uap) int error; error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); - if (error) + if (error != 0) return (error); error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) return (error); msg.msg_iov = iov; msg.msg_flags = MSG_COMPAT; @@ -1067,10 +1067,10 @@ sys_sendmsg(td, uap) int error; error = copyin(uap->msg, &msg, sizeof (msg)); - if (error) + if (error != 0) return (error); error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) return (error); msg.msg_iov = iov; #ifdef COMPAT_OLDSOCK @@ -1091,30 +1091,31 @@ kern_recvit(td, s, mp, fromseg, controlp) { struct uio auio; struct iovec *iov; - int i; - ssize_t len; - int error; struct mbuf *m, *control = NULL; caddr_t ctlbuf; struct file *fp; struct socket *so; struct sockaddr *fromsa = NULL; + cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif + ssize_t len; + int error, i; if (controlp != NULL) *controlp = NULL; AUDIT_ARG_FD(s); - error = getsock_cap(td->td_proc->p_fd, s, CAP_RECV, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, s, + cap_rights_init(&rights, CAP_RECV), &fp, NULL); + if (error != 0) return (error); so = fp->f_data; #ifdef MAC error = mac_socket_check_receive(td->td_ucred, so); - if (error) { + if (error != 0) { fdrop(fp, td); return (error); } @@ -1142,7 +1143,7 @@ kern_recvit(td, s, mp, fromseg, controlp) error = soreceive(so, &fromsa, &auio, NULL, (mp->msg_control || controlp) ? &control : NULL, &mp->msg_flags); - if (error) { + if (error != 0) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -1155,7 +1156,7 @@ kern_recvit(td, s, mp, fromseg, controlp) ktrgenio(s, UIO_READ, ktruio, error); } #endif - if (error) + if (error != 0) goto out; td->td_retval[0] = len - auio.uio_resid; if (mp->msg_name) { @@ -1173,7 +1174,7 @@ kern_recvit(td, s, mp, fromseg, controlp) if (fromseg == UIO_USERSPACE) { error = copyout(fromsa, mp->msg_name, (unsigned)len); - if (error) + if (error != 0) goto out; } else bcopy(fromsa, mp->msg_name, len); @@ -1232,8 +1233,7 @@ out: if (fromsa && KTRPOINT(td, KTR_STRUCT)) ktrsockaddr(fromsa); #endif - if (fromsa) - free(fromsa, M_SONAME); + free(fromsa, M_SONAME); if (error == 0 && controlp != NULL) *controlp = control; @@ -1253,9 +1253,9 @@ recvit(td, s, mp, namelenp) int error; error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL); - if (error) + if (error != 0) return (error); - if (namelenp) { + if (namelenp != NULL) { error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t)); #ifdef COMPAT_OLDSOCK if (mp->msg_flags & MSG_COMPAT) @@ -1284,7 +1284,7 @@ sys_recvfrom(td, uap) if (uap->fromlenaddr) { error = copyin(uap->fromlenaddr, &msg.msg_namelen, sizeof (msg.msg_namelen)); - if (error) + if (error != 0) goto done2; } else { msg.msg_namelen = 0; @@ -1298,7 +1298,7 @@ sys_recvfrom(td, uap) msg.msg_flags = uap->flags; error = recvit(td, uap->s, &msg, uap->fromlenaddr); done2: - return(error); + return (error); } #ifdef COMPAT_OLDSOCK @@ -1326,7 +1326,6 @@ orecv(td, uap) { struct msghdr msg; struct iovec aiov; - int error; msg.msg_name = 0; msg.msg_namelen = 0; @@ -1336,8 +1335,7 @@ orecv(td, uap) aiov.iov_len = uap->len; msg.msg_control = 0; msg.msg_flags = uap->flags; - error = recvit(td, uap->s, &msg, NULL); - return (error); + return (recvit(td, uap->s, &msg, NULL)); } /* @@ -1359,10 +1357,10 @@ orecvmsg(td, uap) int error; error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); - if (error) + if (error != 0) return (error); error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) return (error); msg.msg_flags = uap->flags | MSG_COMPAT; msg.msg_iov = iov; @@ -1389,10 +1387,10 @@ sys_recvmsg(td, uap) int error; error = copyin(uap->msg, &msg, sizeof (msg)); - if (error) + if (error != 0) return (error); error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) return (error); msg.msg_flags = uap->flags; #ifdef COMPAT_OLDSOCK @@ -1420,11 +1418,12 @@ sys_shutdown(td, uap) { struct socket *so; struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->s); - error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_SHUTDOWN, &fp, - NULL); + error = getsock_cap(td->td_proc->p_fd, uap->s, + cap_rights_init(&rights, CAP_SHUTDOWN), &fp, NULL); if (error == 0) { so = fp->f_data; error = soshutdown(so, uap->how); @@ -1460,10 +1459,11 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize) enum uio_seg valseg; socklen_t valsize; { - int error; struct socket *so; struct file *fp; struct sockopt sopt; + cap_rights_t rights; + int error; if (val == NULL && valsize != 0) return (EFAULT); @@ -1487,7 +1487,8 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize) } AUDIT_ARG_FD(s); - error = getsock_cap(td->td_proc->p_fd, s, CAP_SETSOCKOPT, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, s, + cap_rights_init(&rights, CAP_SETSOCKOPT), &fp, NULL); if (error == 0) { so = fp->f_data; error = sosetopt(so, &sopt); @@ -1509,11 +1510,11 @@ sys_getsockopt(td, uap) } */ *uap; { socklen_t valsize; - int error; + int error; if (uap->val) { error = copyin(uap->avalsize, &valsize, sizeof (valsize)); - if (error) + if (error != 0) return (error); } @@ -1539,10 +1540,11 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize) enum uio_seg valseg; socklen_t *valsize; { - int error; - struct socket *so; + struct socket *so; struct file *fp; - struct sockopt sopt; + struct sockopt sopt; + cap_rights_t rights; + int error; if (val == NULL) *valsize = 0; @@ -1566,7 +1568,8 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize) } AUDIT_ARG_FD(s); - error = getsock_cap(td->td_proc->p_fd, s, CAP_GETSOCKOPT, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, s, + cap_rights_init(&rights, CAP_GETSOCKOPT), &fp, NULL); if (error == 0) { so = fp->f_data; error = sogetopt(so, &sopt); @@ -1595,11 +1598,11 @@ getsockname1(td, uap, compat) int error; error = copyin(uap->alen, &len, sizeof(len)); - if (error) + if (error != 0) return (error); error = kern_getsockname(td, uap->fdes, &sa, &len); - if (error) + if (error != 0) return (error); if (len != 0) { @@ -1621,19 +1624,21 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, { struct socket *so; struct file *fp; + cap_rights_t rights; socklen_t len; int error; AUDIT_ARG_FD(fd); - error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETSOCKNAME, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_GETSOCKNAME), &fp, NULL); + if (error != 0) return (error); so = fp->f_data; *sa = NULL; CURVNET_SET(so->so_vnet); error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa); CURVNET_RESTORE(); - if (error) + if (error != 0) goto bad; if (*sa == NULL) len = 0; @@ -1646,7 +1651,7 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, #endif bad: fdrop(fp, td); - if (error && *sa) { + if (error != 0 && *sa != NULL) { free(*sa, M_SONAME); *sa = NULL; } @@ -1692,11 +1697,11 @@ getpeername1(td, uap, compat) int error; error = copyin(uap->alen, &len, sizeof (len)); - if (error) + if (error != 0) return (error); error = kern_getpeername(td, uap->fdes, &sa, &len); - if (error) + if (error != 0) return (error); if (len != 0) { @@ -1718,12 +1723,14 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, { struct socket *so; struct file *fp; + cap_rights_t rights; socklen_t len; int error; AUDIT_ARG_FD(fd); - error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETPEERNAME, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_GETPEERNAME), &fp, NULL); + if (error != 0) return (error); so = fp->f_data; if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { @@ -1734,7 +1741,7 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, CURVNET_SET(so->so_vnet); error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa); CURVNET_RESTORE(); - if (error) + if (error != 0) goto bad; if (*sa == NULL) len = 0; @@ -1746,7 +1753,7 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, ktrsockaddr(*sa); #endif bad: - if (error && *sa) { + if (error != 0 && *sa != NULL) { free(*sa, M_SONAME); *sa = NULL; } @@ -1798,7 +1805,7 @@ sockargs(mp, buf, buflen, type) m = m_get2(buflen, M_WAITOK, type, 0); m->m_len = buflen; error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); - if (error) + if (error != 0) (void) m_free(m); else { *mp = m; @@ -1830,7 +1837,7 @@ getsockaddr(namp, uaddr, len) return (EINVAL); sa = malloc(len, M_SONAME, M_WAITOK); error = copyin(uaddr, sa, len); - if (error) { + if (error != 0) { free(sa, M_SONAME); } else { #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN @@ -1907,6 +1914,7 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) struct sf_hdtr hdtr; struct uio *hdr_uio, *trl_uio; struct file *fp; + cap_rights_t rights; int error; if (uap->offset < 0) @@ -1916,16 +1924,16 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) if (uap->hdtr != NULL) { error = copyin(uap->hdtr, &hdtr, sizeof(hdtr)); - if (error) + if (error != 0) goto out; if (hdtr.headers != NULL) { error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio); - if (error) + if (error != 0) goto out; } if (hdtr.trailers != NULL) { error = copyinuio(hdtr.trailers, hdtr.trl_cnt, &trl_uio); - if (error) + if (error != 0) goto out; } @@ -1937,18 +1945,18 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) * sendfile(2) can start at any offset within a file so we require * CAP_READ+CAP_SEEK = CAP_PREAD. */ - if ((error = fget_read(td, uap->fd, CAP_PREAD, &fp)) != 0) + if ((error = fget_read(td, uap->fd, + cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) { goto out; + } error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset, uap->nbytes, uap->sbytes, uap->flags, compat ? SFK_COMPAT : 0, td); fdrop(fp, td); out: - if (hdr_uio) - free(hdr_uio, M_IOV); - if (trl_uio) - free(trl_uio, M_IOV); + free(hdr_uio, M_IOV); + free(trl_uio, M_IOV); return (error); } @@ -1983,10 +1991,10 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio, struct sf_buf *sf; struct vm_page *pg; struct vattr va; - off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0; - int error, hdrlen = 0, mnw = 0; - int bsize; struct sendfile_sync *sfs = NULL; + cap_rights_t rights; + off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0; + int bsize, error, hdrlen = 0, mnw = 0; vn_lock(vp, LK_SHARED | LK_RETRY); if (vp->v_type == VREG) { @@ -2030,8 +2038,9 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio, * The socket must be a stream socket and connected. * Remember if it a blocking or non-blocking socket. */ - if ((error = getsock_cap(td->td_proc->p_fd, sockfd, CAP_SEND, - &sock_fp, NULL)) != 0) + error = getsock_cap(td->td_proc->p_fd, sockfd, + cap_rights_init(&rights, CAP_SEND), &sock_fp, NULL); + if (error != 0) goto out; so = sock_fp->f_data; if (so->so_type != SOCK_STREAM) { @@ -2058,7 +2067,7 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio, #ifdef MAC error = mac_socket_check_send(td->td_ucred, so); - if (error) + if (error != 0) goto out; #endif @@ -2173,7 +2182,7 @@ retry_space: * been interrupted by a signal. If we've sent anything * then return bytes sent, otherwise return the error. */ - if (error) { + if (error != 0) { SOCKBUF_UNLOCK(&so->so_snd); goto done; } @@ -2265,10 +2274,10 @@ retry_space: IO_VMIO | ((readahead / bsize) << IO_SEQSHIFT), td->td_ucred, NOCRED, &resid, td); SFSTAT_INC(sf_iocnt); - if (error) + if (error != 0) VM_OBJECT_WLOCK(obj); } - if (error) { + if (error != 0) { vm_page_lock(pg); vm_page_unwire(pg, 0); /* @@ -2393,7 +2402,7 @@ retry_space: /* Quit outer loop on error or when we're done. */ if (done) break; - if (error) + if (error != 0) goto done; } @@ -2460,21 +2469,22 @@ sys_sctp_peeloff(td, uap) { #if (defined(INET) || defined(INET6)) && defined(SCTP) struct file *nfp = NULL; - int error; struct socket *head, *so; - int fd; + cap_rights_t rights; u_int fflag; + int error, fd; AUDIT_ARG_FD(uap->sd); - error = fgetsock(td, uap->sd, CAP_PEELOFF, &head, &fflag); - if (error) + error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF), + &head, &fflag); + if (error != 0) goto done2; if (head->so_proto->pr_protocol != IPPROTO_SCTP) { error = EOPNOTSUPP; goto done; } error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name); - if (error) + if (error != 0) goto done; /* * At this point we know we do have a assoc to pull @@ -2483,7 +2493,7 @@ sys_sctp_peeloff(td, uap) */ error = falloc(td, &nfp, &fd, 0); - if (error) + if (error != 0) goto done; td->td_retval[0] = fd; @@ -2513,7 +2523,7 @@ sys_sctp_peeloff(td, uap) ACCEPT_UNLOCK(); finit(nfp, fflag, DTYPE_SOCKET, so, &socketops); error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name); - if (error) + if (error != 0) goto noconnection; if (head->so_sigio != NULL) fsetown(fgetown(&head->so_sigio), &so->so_sigio); @@ -2523,7 +2533,7 @@ noconnection: * close the new descriptor, assuming someone hasn't ripped it * out from under us. */ - if (error) + if (error != 0) fdclose(td->td_proc->p_fd, nfp, fd, td); /* @@ -2558,7 +2568,6 @@ sys_sctp_generic_sendmsg (td, uap) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; - int error = 0, len; struct sockaddr *to = NULL; #ifdef KTRACE struct uio *ktruio = NULL; @@ -2566,27 +2575,28 @@ sys_sctp_generic_sendmsg (td, uap) struct uio auio; struct iovec iov[1]; cap_rights_t rights; + int error = 0, len; - if (uap->sinfo) { + if (uap->sinfo != NULL) { error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); - if (error) + if (error != 0) return (error); u_sinfo = &sinfo; } - rights = CAP_SEND; - if (uap->tolen) { + cap_rights_init(&rights, CAP_SEND); + if (uap->tolen != 0) { error = getsockaddr(&to, uap->to, uap->tolen); - if (error) { + if (error != 0) { to = NULL; goto sctp_bad2; } - rights |= CAP_CONNECT; + cap_rights_set(&rights, CAP_CONNECT); } AUDIT_ARG_FD(uap->sd); - error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL); + if (error != 0) goto sctp_bad; #ifdef KTRACE if (to && (KTRPOINT(td, KTR_STRUCT))) @@ -2603,7 +2613,7 @@ sys_sctp_generic_sendmsg (td, uap) } #ifdef MAC error = mac_socket_check_send(td->td_ucred, so); - if (error) + if (error != 0) goto sctp_bad; #endif /* MAC */ @@ -2616,11 +2626,10 @@ sys_sctp_generic_sendmsg (td, uap) auio.uio_resid = 0; len = auio.uio_resid = uap->mlen; CURVNET_SET(so->so_vnet); - error = sctp_lower_sosend(so, to, &auio, - (struct mbuf *)NULL, (struct mbuf *)NULL, - uap->flags, u_sinfo, td); + error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, + (struct mbuf *)NULL, uap->flags, u_sinfo, td); CURVNET_RESTORE(); - if (error) { + if (error != 0) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -2641,11 +2650,10 @@ sys_sctp_generic_sendmsg (td, uap) } #endif /* KTRACE */ sctp_bad: - if (fp) + if (fp != NULL) fdrop(fp, td); sctp_bad2: - if (to) - free(to, M_SONAME); + free(to, M_SONAME); return (error); #else /* SCTP */ return (EOPNOTSUPP); @@ -2669,8 +2677,6 @@ sys_sctp_generic_sendmsg_iov(td, uap) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; - int error=0, i; - ssize_t len; struct sockaddr *to = NULL; #ifdef KTRACE struct uio *ktruio = NULL; @@ -2678,26 +2684,28 @@ sys_sctp_generic_sendmsg_iov(td, uap) struct uio auio; struct iovec *iov, *tiov; cap_rights_t rights; + ssize_t len; + int error, i; - if (uap->sinfo) { + if (uap->sinfo != NULL) { error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); - if (error) + if (error != 0) return (error); u_sinfo = &sinfo; } - rights = CAP_SEND; - if (uap->tolen) { + cap_rights_init(&rights, CAP_SEND); + if (uap->tolen != 0) { error = getsockaddr(&to, uap->to, uap->tolen); - if (error) { + if (error != 0) { to = NULL; goto sctp_bad2; } - rights |= CAP_CONNECT; + cap_rights_set(&rights, CAP_CONNECT); } AUDIT_ARG_FD(uap->sd); - error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL); - if (error) + error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL); + if (error != 0) goto sctp_bad1; #ifdef COMPAT_FREEBSD32 @@ -2707,7 +2715,7 @@ sys_sctp_generic_sendmsg_iov(td, uap) else #endif error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) goto sctp_bad1; #ifdef KTRACE if (to && (KTRPOINT(td, KTR_STRUCT))) @@ -2721,7 +2729,7 @@ sys_sctp_generic_sendmsg_iov(td, uap) } #ifdef MAC error = mac_socket_check_send(td->td_ucred, so); - if (error) + if (error != 0) goto sctp_bad; #endif /* MAC */ @@ -2745,7 +2753,7 @@ sys_sctp_generic_sendmsg_iov(td, uap) (struct mbuf *)NULL, (struct mbuf *)NULL, uap->flags, u_sinfo, td); CURVNET_RESTORE(); - if (error) { + if (error != 0) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -2768,11 +2776,10 @@ sys_sctp_generic_sendmsg_iov(td, uap) sctp_bad: free(iov, M_IOV); sctp_bad1: - if (fp) + if (fp != NULL) fdrop(fp, td); sctp_bad2: - if (to) - free(to, M_SONAME); + free(to, M_SONAME); return (error); #else /* SCTP */ return (EOPNOTSUPP); @@ -2800,19 +2807,18 @@ sys_sctp_generic_recvmsg(td, uap) struct socket *so; struct file *fp = NULL; struct sockaddr *fromsa; - int fromlen; - ssize_t len; - int i, msg_flags; - int error = 0; + cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif + ssize_t len; + int error, fromlen, i, msg_flags; AUDIT_ARG_FD(uap->sd); - error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_RECV, &fp, NULL); - if (error) { + error = getsock_cap(td->td_proc->p_fd, uap->sd, + cap_rights_init(&rights, CAP_RECV), &fp, NULL); + if (error != 0) return (error); - } #ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) error = freebsd32_copyiniov((struct iovec32 *)uap->iov, @@ -2820,7 +2826,7 @@ sys_sctp_generic_recvmsg(td, uap) else #endif error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); - if (error) + if (error != 0) goto out1; so = fp->f_data; @@ -2830,25 +2836,21 @@ sys_sctp_generic_recvmsg(td, uap) } #ifdef MAC error = mac_socket_check_receive(td->td_ucred, so); - if (error) { + if (error != 0) goto out; - } #endif /* MAC */ - if (uap->fromlenaddr) { - error = copyin(uap->fromlenaddr, - &fromlen, sizeof (fromlen)); - if (error) { + if (uap->fromlenaddr != NULL) { + error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen)); + if (error != 0) goto out; - } } else { fromlen = 0; } if (uap->msg_flags) { error = copyin(uap->msg_flags, &msg_flags, sizeof (int)); - if (error) { + if (error != 0) goto out; - } } else { msg_flags = 0; } @@ -2879,7 +2881,7 @@ sys_sctp_generic_recvmsg(td, uap) fromsa, fromlen, &msg_flags, (struct sctp_sndrcvinfo *)&sinfo, 1); CURVNET_RESTORE(); - if (error) { + if (error != 0) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -2893,7 +2895,7 @@ sys_sctp_generic_recvmsg(td, uap) ktrgenio(uap->sd, UIO_READ, ktruio, error); } #endif /* KTRACE */ - if (error) + if (error != 0) goto out; td->td_retval[0] = len - auio.uio_resid; @@ -2904,13 +2906,12 @@ sys_sctp_generic_recvmsg(td, uap) else { len = MIN(len, fromsa->sa_len); error = copyout(fromsa, uap->from, (size_t)len); - if (error) + if (error != 0) goto out; } error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t)); - if (error) { + if (error != 0) goto out; - } } #ifdef KTRACE if (KTRPOINT(td, KTR_STRUCT)) @@ -2918,14 +2919,13 @@ sys_sctp_generic_recvmsg(td, uap) #endif if (uap->msg_flags) { error = copyout(&msg_flags, uap->msg_flags, sizeof (int)); - if (error) { + if (error != 0) goto out; - } } out: free(iov, M_IOV); out1: - if (fp) + if (fp != NULL) fdrop(fp, td); return (error); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 7a4db04..c0a5d2e 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -464,6 +464,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) struct unpcb *unp; struct vnode *vp; struct mount *mp; + cap_rights_t rights; char *buf; unp = sotounpcb(so); @@ -502,7 +503,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) restart: NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, - UIO_SYSSPACE, buf, fd, CAP_BINDAT, td); + UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_BINDAT), td); /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ error = namei(&nd); if (error) @@ -1276,10 +1277,11 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam, struct vnode *vp; struct socket *so2, *so3; struct unpcb *unp, *unp2, *unp3; - int error, len; struct nameidata nd; char buf[SOCK_MAXADDRLEN]; struct sockaddr *sa; + cap_rights_t rights; + int error, len; UNP_LINK_WLOCK_ASSERT(); @@ -1305,7 +1307,7 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam, sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK); NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, - UIO_SYSSPACE, buf, fd, CAP_CONNECTAT, td); + UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_CONNECTAT), td); error = namei(&nd); if (error) vp = NULL; diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c index 1c9923d..362792b 100644 --- a/sys/kern/vfs_acl.c +++ b/sys/kern/vfs_acl.c @@ -399,9 +399,11 @@ int sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) { struct file *fp; + cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_GET, &fp); + error = getvnode(td->td_proc->p_fd, uap->filedes, + cap_rights_init(&rights, CAP_ACL_GET), &fp); if (error == 0) { error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); fdrop(fp, td); @@ -416,9 +418,11 @@ int sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) { struct file *fp; + cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_SET, &fp); + error = getvnode(td->td_proc->p_fd, uap->filedes, + cap_rights_init(&rights, CAP_ACL_SET), &fp); if (error == 0) { error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); fdrop(fp, td); @@ -469,10 +473,11 @@ int sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) { struct file *fp; + cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_DELETE, - &fp); + error = getvnode(td->td_proc->p_fd, uap->filedes, + cap_rights_init(&rights, CAP_ACL_DELETE), &fp); if (error == 0) { error = vacl_delete(td, fp->f_vnode, uap->type); fdrop(fp, td); @@ -523,10 +528,11 @@ int sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) { struct file *fp; + cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_CHECK, - &fp); + error = getvnode(td->td_proc->p_fd, uap->filedes, + cap_rights_init(&rights, CAP_ACL_CHECK), &fp); if (error == 0) { error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); fdrop(fp, td); diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index a66f7c2..7f9f881 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -1567,6 +1567,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, int type, struct aiocb_ops *ops) { struct proc *p = td->td_proc; + cap_rights_t rights; struct file *fp; struct socket *so; struct aiocblist *aiocbe, *cb; @@ -1647,19 +1648,21 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, fd = aiocbe->uaiocb.aio_fildes; switch (opcode) { case LIO_WRITE: - error = fget_write(td, fd, CAP_PWRITE, &fp); + error = fget_write(td, fd, + cap_rights_init(&rights, CAP_PWRITE), &fp); break; case LIO_READ: - error = fget_read(td, fd, CAP_PREAD, &fp); + error = fget_read(td, fd, + cap_rights_init(&rights, CAP_PREAD), &fp); break; case LIO_SYNC: - error = fget(td, fd, CAP_FSYNC, &fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_FSYNC), &fp); break; case LIO_MLOCK: fp = NULL; break; case LIO_NOP: - error = fget(td, fd, CAP_NONE, &fp); + error = fget(td, fd, cap_rights_init(&rights), &fp); break; default: error = EINVAL; @@ -2047,7 +2050,7 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) struct vnode *vp; /* Lookup file object. */ - error = fget(td, uap->fd, 0, &fp); + error = fget(td, uap->fd, NULL, &fp); if (error) return (error); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 04eab14..37ef663 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3994,7 +3994,7 @@ vfs_drain_busy_pages(struct buf *bp) m = bp->b_pages[i]; if (vm_page_xbusied(m)) { for (; last_busied < i; last_busied++) - vm_page_xbusy(bp->b_pages[last_busied]); + vm_page_sbusy(bp->b_pages[last_busied]); while (vm_page_xbusied(m)) { vm_page_lock(m); VM_OBJECT_WUNLOCK(bp->b_bufobj->bo_object); @@ -4004,7 +4004,7 @@ vfs_drain_busy_pages(struct buf *bp) } } for (i = 0; i < last_busied; i++) - vm_page_xunbusy(bp->b_pages[i]); + vm_page_sunbusy(bp->b_pages[i]); } /* diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 700a70c..bc7b942 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -216,6 +216,7 @@ sys_extattr_set_fd(td, uap) { struct file *fp; char attrname[EXTATTR_MAXNAMELEN]; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); @@ -225,7 +226,8 @@ sys_extattr_set_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_SET, &fp); + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) return (error); @@ -389,6 +391,7 @@ sys_extattr_get_fd(td, uap) { struct file *fp; char attrname[EXTATTR_MAXNAMELEN]; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); @@ -398,7 +401,8 @@ sys_extattr_get_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_GET, &fp); + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_EXTATTR_GET), &fp); if (error) return (error); @@ -531,6 +535,7 @@ sys_extattr_delete_fd(td, uap) { struct file *fp; char attrname[EXTATTR_MAXNAMELEN]; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); @@ -540,8 +545,8 @@ sys_extattr_delete_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_DELETE, - &fp); + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_EXTATTR_DELETE), &fp); if (error) return (error); @@ -687,11 +692,13 @@ sys_extattr_list_fd(td, uap) } */ *uap; { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); AUDIT_ARG_VALUE(uap->attrnamespace); - error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_LIST, &fp); + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_EXTATTR_LIST), &fp); if (error) return (error); diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 7fe1908..d4d0166 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -222,20 +222,26 @@ namei(struct nameidata *ndp) dp = ndp->ni_startdir; error = 0; } else if (ndp->ni_dirfd != AT_FDCWD) { + cap_rights_t rights; + + rights = ndp->ni_rightsneeded; + cap_rights_set(&rights, CAP_LOOKUP); + if (cnp->cn_flags & AUDITVNODE1) AUDIT_ARG_ATFD1(ndp->ni_dirfd); if (cnp->cn_flags & AUDITVNODE2) AUDIT_ARG_ATFD2(ndp->ni_dirfd); error = fgetvp_rights(td, ndp->ni_dirfd, - ndp->ni_rightsneeded | CAP_LOOKUP, - &ndp->ni_filecaps, &dp); + &rights, &ndp->ni_filecaps, &dp); #ifdef CAPABILITIES /* * If file descriptor doesn't have all rights, * all lookups relative to it must also be * strictly relative. */ - if (ndp->ni_filecaps.fc_rights != CAP_ALL || + CAP_ALL(&rights); + if (!cap_rights_contains(&ndp->ni_filecaps.fc_rights, + &rights) || ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL || ndp->ni_filecaps.fc_nioctls != -1) { ndp->ni_strictrelative = 1; @@ -1059,6 +1065,27 @@ bad: return (error); } +void +NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, + const char *namep, int dirfd, struct vnode *startdir, cap_rights_t *rightsp, + struct thread *td) +{ + + ndp->ni_cnd.cn_nameiop = op; + ndp->ni_cnd.cn_flags = flags; + ndp->ni_segflg = segflg; + ndp->ni_dirp = namep; + ndp->ni_dirfd = dirfd; + ndp->ni_startdir = startdir; + ndp->ni_strictrelative = 0; + if (rightsp != NULL) + ndp->ni_rightsneeded = *rightsp; + else + cap_rights_init(&ndp->ni_rightsneeded); + filecaps_init(&ndp->ni_filecaps); + ndp->ni_cnd.cn_thread = td; +} + /* * Free data allocated by namei(); see namei(9) for details. */ diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 493bb98..8f92e10 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1269,8 +1269,16 @@ dounmount(mp, flags, td) } mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ; /* Allow filesystems to detect that a forced unmount is in progress. */ - if (flags & MNT_FORCE) + if (flags & MNT_FORCE) { mp->mnt_kern_flag |= MNTK_UNMOUNTF; + MNT_IUNLOCK(mp); + /* + * Must be done after setting MNTK_UNMOUNTF and before + * waiting for mnt_lockref to become 0. + */ + VFS_PURGE(mp); + MNT_ILOCK(mp); + } error = 0; if (mp->mnt_lockref) { mp->mnt_kern_flag |= MNTK_DRAINING; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 2877ad2..4b82df8 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -181,8 +181,8 @@ sys_quotactl(td, uap) } */ *uap; { struct mount *mp; - int error; struct nameidata nd; + int error; AUDIT_ARG_CMD(uap->cmd); AUDIT_ARG_UID(uap->uid); @@ -198,7 +198,7 @@ sys_quotactl(td, uap) vput(nd.ni_vp); error = vfs_busy(mp, 0); vfs_rel(mp); - if (error) + if (error != 0) return (error); error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg); @@ -291,13 +291,13 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, { struct mount *mp; struct statfs *sp, sb; - int error; struct nameidata nd; + int error; NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, td); error = namei(&nd); - if (error) + if (error != 0) return (error); mp = nd.ni_vp->v_mount; vfs_ref(mp); @@ -305,11 +305,11 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, vput(nd.ni_vp); error = vfs_busy(mp, 0); vfs_rel(mp); - if (error) + if (error != 0) return (error); #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); - if (error) + if (error != 0) goto out; #endif /* @@ -320,7 +320,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp); - if (error) + if (error != 0) goto out; if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); @@ -367,11 +367,13 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) struct mount *mp; struct statfs *sp, sb; struct vnode *vp; + cap_rights_t rights; int error; AUDIT_ARG_FD(fd); - error = getvnode(td->td_proc->p_fd, fd, CAP_FSTATFS, &fp); - if (error) + error = getvnode(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_FSTATFS), &fp); + if (error != 0) return (error); vp = fp->f_vnode; vn_lock(vp, LK_SHARED | LK_RETRY); @@ -389,11 +391,11 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) } error = vfs_busy(mp, 0); vfs_rel(mp); - if (error) + if (error != 0) return (error); #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); - if (error) + if (error != 0) goto out; #endif /* @@ -404,7 +406,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp); - if (error) + if (error != 0) goto out; if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); @@ -523,7 +525,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, bcopy(sp, sfsp, sizeof(*sp)); else /* if (bufseg == UIO_USERSPACE) */ { error = copyout(sp, sfsp, sizeof(*sp)); - if (error) { + if (error != 0) { vfs_unbusy(mp); return (error); } @@ -568,7 +570,7 @@ freebsd4_statfs(td, uap) int error; error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf); - if (error) + if (error != 0) return (error); cvtstatfs(&sf, &osb); return (copyout(&osb, uap->buf, sizeof(osb))); @@ -596,7 +598,7 @@ freebsd4_fstatfs(td, uap) int error; error = kern_fstatfs(td, uap->fd, &sf); - if (error) + if (error != 0) return (error); cvtstatfs(&sf, &osb); return (copyout(&osb, uap->buf, sizeof(osb))); @@ -667,10 +669,10 @@ freebsd4_fhstatfs(td, uap) int error; error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); - if (error) + if (error != 0) return (error); error = kern_fhstatfs(td, fh, &sf); - if (error) + if (error != 0) return (error); cvtstatfs(&sf, &osb); return (copyout(&osb, uap->buf, sizeof(osb))); @@ -730,10 +732,13 @@ sys_fchdir(td, uap) struct vnode *vp, *tdp, *vpold; struct mount *mp; struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); - if ((error = getvnode(fdp, uap->fd, CAP_FCHDIR, &fp)) != 0) + error = getvnode(fdp, uap->fd, cap_rights_init(&rights, CAP_FCHDIR), + &fp); + if (error != 0) return (error); vp = fp->f_vnode; VREF(vp); @@ -746,12 +751,12 @@ sys_fchdir(td, uap) continue; error = VFS_ROOT(mp, LK_SHARED, &tdp); vfs_unbusy(mp); - if (error) + if (error != 0) break; vput(vp); vp = tdp; } - if (error) { + if (error != 0) { vput(vp); return (error); } @@ -787,9 +792,9 @@ int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) { register struct filedesc *fdp = td->td_proc->p_fd; - int error; struct nameidata nd; struct vnode *vp; + int error; NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, td); @@ -866,21 +871,23 @@ sys_chroot(td, uap) char *path; } */ *uap; { - int error; struct nameidata nd; + int error; error = priv_check(td, PRIV_VFS_CHROOT); - if (error) + if (error != 0) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); - if (error) + if (error != 0) goto error; - if ((error = change_dir(nd.ni_vp, td)) != 0) + error = change_dir(nd.ni_vp, td); + if (error != 0) goto e_vunlock; #ifdef MAC - if ((error = mac_vnode_check_chroot(td->td_ucred, nd.ni_vp))) + error = mac_vnode_check_chroot(td->td_ucred, nd.ni_vp); + if (error != 0) goto e_vunlock; #endif VOP_UNLOCK(nd.ni_vp, 0); @@ -904,18 +911,19 @@ change_dir(vp, td) struct vnode *vp; struct thread *td; { +#ifdef MAC int error; +#endif ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked"); if (vp->v_type != VDIR) return (ENOTDIR); #ifdef MAC error = mac_vnode_check_chdir(td->td_ucred, vp); - if (error) + if (error != 0) return (error); #endif - error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); - return (error); + return (VOP_ACCESS(vp, VEXEC, td->td_ucred, td)); } /* @@ -937,7 +945,7 @@ change_root(vp, td) if (chroot_allow_open_directories == 0 || (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { error = chroot_refuse_vdir_fds(fdp); - if (error) { + if (error != 0) { FILEDESC_XUNLOCK(fdp); return (error); } @@ -954,42 +962,39 @@ change_root(vp, td) return (0); } -static __inline cap_rights_t -flags_to_rights(int flags) +static __inline void +flags_to_rights(int flags, cap_rights_t *rightsp) { - cap_rights_t rights = 0; if (flags & O_EXEC) { - rights |= CAP_FEXECVE; + cap_rights_set(rightsp, CAP_FEXECVE); } else { switch ((flags & O_ACCMODE)) { case O_RDONLY: - rights |= CAP_READ; + cap_rights_set(rightsp, CAP_READ); break; case O_RDWR: - rights |= CAP_READ; + cap_rights_set(rightsp, CAP_READ); /* FALLTHROUGH */ case O_WRONLY: - rights |= CAP_WRITE; + cap_rights_set(rightsp, CAP_WRITE); if (!(flags & (O_APPEND | O_TRUNC))) - rights |= CAP_SEEK; + cap_rights_set(rightsp, CAP_SEEK); break; } } if (flags & O_CREAT) - rights |= CAP_CREATE; + cap_rights_set(rightsp, CAP_CREATE); if (flags & O_TRUNC) - rights |= CAP_FTRUNCATE; + cap_rights_set(rightsp, CAP_FTRUNCATE); if (flags & (O_SYNC | O_FSYNC)) - rights |= CAP_FSYNC; + cap_rights_set(rightsp, CAP_FSYNC); if (flags & (O_EXLOCK | O_SHLOCK)) - rights |= CAP_FLOCK; - - return (rights); + cap_rights_set(rightsp, CAP_FLOCK); } /* @@ -1048,15 +1053,17 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; - int cmode; - int indx = -1, error; struct nameidata nd; - cap_rights_t rights_needed = CAP_LOOKUP; + cap_rights_t rights; + int cmode, error, indx; + + indx = -1; AUDIT_ARG_FFLAGS(flags); AUDIT_ARG_MODE(mode); /* XXX: audit dirfd */ - rights_needed |= flags_to_rights(flags); + cap_rights_init(&rights, CAP_LOOKUP); + flags_to_rights(flags, &rights); /* * Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags * may be specified. @@ -1074,7 +1081,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, * Allocate the file descriptor, but don't install a descriptor yet. */ error = falloc_noinstall(td, &fp); - if (error) + if (error != 0) return (error); /* * An extra reference on `fp' has been held for us by @@ -1082,12 +1089,12 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, */ /* Set the flags early so the finit in devfs can pick them up. */ fp->f_flag = flags & FMASK; - cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + cmode = ((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT; NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd, - rights_needed, td); + &rights, td); td->td_dupfd = -1; /* XXX check for fdopen */ error = vn_open(&nd, &flags, cmode, fp); - if (error) { + if (error != 0) { /* * If the vn_open replaced the method vector, something * wonderous happened deep below and we just pass it up @@ -1131,14 +1138,14 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, if (fp->f_ops == &badfileops) { KASSERT(vp->v_type != VFIFO, ("Unexpected fifo.")); fp->f_seqcount = 1; - finit(fp, (flags & FMASK) | (fp->f_flag & FHASLOCK), DTYPE_VNODE, - vp, &vnops); + finit(fp, (flags & FMASK) | (fp->f_flag & FHASLOCK), + DTYPE_VNODE, vp, &vnops); } VOP_UNLOCK(vp, 0); if (flags & O_TRUNC) { error = fo_truncate(fp, 0, td->td_ucred, td); - if (error) + if (error != 0) goto bad; } success: @@ -1255,9 +1262,9 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct vnode *vp; struct mount *mp; struct vattr vattr; - int error; - int whiteout = 0; struct nameidata nd; + cap_rights_t rights; + int error, whiteout = 0; AUDIT_ARG_MODE(mode); AUDIT_ARG_DEV(dev); @@ -1280,12 +1287,12 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, error = EINVAL; break; } - if (error) + if (error != 0) return (error); restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - pathseg, path, fd, CAP_MKNODAT, td); + pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT), td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -1333,7 +1340,7 @@ restart: error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, &vattr); #endif - if (!error) { + if (error == 0) { if (whiteout) error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); else { @@ -1398,14 +1405,15 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg, { struct mount *mp; struct vattr vattr; - int error; struct nameidata nd; + cap_rights_t rights; + int error; AUDIT_ARG_MODE(mode); restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - pathseg, path, fd, CAP_MKFIFOAT, td); + pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT), td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { @@ -1430,7 +1438,7 @@ restart: #ifdef MAC error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, &vattr); - if (error) + if (error != 0) goto out; #endif error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); @@ -1514,13 +1522,13 @@ can_hardlink(struct vnode *vp, struct ucred *cred) if (hardlink_check_uid && cred->cr_uid != va.va_uid) { error = priv_check_cred(cred, PRIV_VFS_LINK, 0); - if (error) + if (error != 0) return (error); } if (hardlink_check_gid && !groupmember(va.va_gid, cred)) { error = priv_check_cred(cred, PRIV_VFS_LINK, 0); - if (error) + if (error != 0) return (error); } @@ -1541,6 +1549,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2, struct vnode *vp; struct mount *mp; struct nameidata nd; + cap_rights_t rights; int error; bwillwrite(); @@ -1559,7 +1568,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2, return (error); } NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2, - segflg, path2, fd2, CAP_LINKAT, td); + segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), td); if ((error = namei(&nd)) == 0) { if (nd.ni_vp != NULL) { if (nd.ni_dvp == nd.ni_vp) @@ -1638,8 +1647,9 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, struct mount *mp; struct vattr vattr; char *syspath; - int error; struct nameidata nd; + int error; + cap_rights_t rights; if (segflg == UIO_SYSSPACE) { syspath = path1; @@ -1652,7 +1662,7 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - segflg, path2, fd, CAP_SYMLINKAT, td); + segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT), td); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { @@ -1678,7 +1688,7 @@ restart: vattr.va_type = VLNK; error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, &vattr); - if (error) + if (error != 0) goto out2; #endif error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); @@ -1706,16 +1716,16 @@ sys_undelete(td, uap) char *path; } */ *uap; { - int error; struct mount *mp; struct nameidata nd; + int error; restart: bwillwrite(); NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); - if (error) + if (error != 0) return (error); if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { @@ -1797,14 +1807,15 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, { struct mount *mp; struct vnode *vp; - int error; struct nameidata nd; struct stat sb; + cap_rights_t rights; + int error; restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1, - pathseg, path, fd, CAP_UNLINKAT, td); + pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td); if ((error = namei(&nd)) != 0) return (error == EINVAL ? EPERM : error); vp = nd.ni_vp; @@ -1839,7 +1850,7 @@ restart: #ifdef MAC error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp, &nd.ni_cnd); - if (error) + if (error != 0) goto out; #endif vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK); @@ -1880,10 +1891,12 @@ sys_lseek(td, uap) } */ *uap; { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); - if ((error = fget(td, uap->fd, CAP_SEEK, &fp)) != 0) + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEEK), &fp); + if (error != 0) return (error); error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE) != 0 ? fo_seek(fp, uap->offset, uap->whence, td) : ESPIPE; @@ -1949,8 +1962,8 @@ vn_access(vp, user_flags, cred, td) struct ucred *cred; struct thread *td; { - int error; accmode_t accmode; + int error; /* Flags == 0 means only check for existence. */ error = 0; @@ -1964,7 +1977,7 @@ vn_access(vp, user_flags, cred, td) accmode |= VEXEC; #ifdef MAC error = mac_vnode_check_access(cred, vp, accmode); - if (error) + if (error != 0) return (error); #endif if ((accmode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) @@ -2026,6 +2039,7 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct ucred *cred, *tmpcred; struct vnode *vp; struct nameidata nd; + cap_rights_t rights; int error; /* @@ -2042,7 +2056,8 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg, cred = tmpcred = td->td_ucred; AUDIT_ARG_VALUE(amode); NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | - AUDITVNODE1, pathseg, path, fd, CAP_FSTAT, td); + AUDITVNODE1, pathseg, path, fd, cap_rights_init(&rights, CAP_FSTAT), + td); if ((error = namei(&nd)) != 0) goto out1; vp = nd.ni_vp; @@ -2109,11 +2124,10 @@ ostat(td, uap) int error; error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); - if (error) + if (error != 0) return (error); cvtstat(&sb, &osb); - error = copyout(&osb, uap->ub, sizeof (osb)); - return (error); + return (copyout(&osb, uap->ub, sizeof (osb))); } /* @@ -2138,11 +2152,10 @@ olstat(td, uap) int error; error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); - if (error) + if (error != 0) return (error); cvtstat(&sb, &osb); - error = copyout(&osb, uap->ub, sizeof (osb)); - return (error); + return (copyout(&osb, uap->ub, sizeof (osb))); } /* @@ -2244,6 +2257,7 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path, { struct nameidata nd; struct stat sb; + cap_rights_t rights; int error; if (flag & ~AT_SYMLINK_NOFOLLOW) @@ -2251,12 +2265,12 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path, NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd, - CAP_FSTAT, td); + cap_rights_init(&rights, CAP_FSTAT), td); if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); - if (!error) { + if (error == 0) { SDT_PROBE(vfs, , stat, mode, path, sb.st_mode, 0, 0, 0); if (S_ISREG(sb.st_mode)) SDT_PROBE(vfs, , stat, reg, path, pathseg, 0, 0, 0); @@ -2265,7 +2279,7 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path, } NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_vp); - if (error) + if (error != 0) return (error); *sbp = sb; #ifdef KTRACE @@ -2317,6 +2331,7 @@ cvtnstat(sb, nsb) struct stat *sb; struct nstat *nsb; { + bzero(nsb, sizeof *nsb); nsb->st_dev = sb->st_dev; nsb->st_ino = sb->st_ino; @@ -2355,11 +2370,10 @@ sys_nstat(td, uap) int error; error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); - if (error) + if (error != 0) return (error); cvtnstat(&sb, &nsb); - error = copyout(&nsb, uap->ub, sizeof (nsb)); - return (error); + return (copyout(&nsb, uap->ub, sizeof (nsb))); } /* @@ -2384,11 +2398,10 @@ sys_nlstat(td, uap) int error; error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); - if (error) + if (error != 0) return (error); cvtnstat(&sb, &nsb); - error = copyout(&nsb, uap->ub, sizeof (nsb)); - return (error); + return (copyout(&nsb, uap->ub, sizeof (nsb))); } /* @@ -2508,8 +2521,8 @@ kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct vnode *vp; struct iovec aiov; struct uio auio; - int error; struct nameidata nd; + int error; if (count > IOSIZE_MAX) return (EINVAL); @@ -2523,7 +2536,7 @@ kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, vp = nd.ni_vp; #ifdef MAC error = mac_vnode_check_readlink(td->td_ucred, vp); - if (error) { + if (error != 0) { vput(vp); return (error); } @@ -2556,9 +2569,9 @@ setfflags(td, vp, flags) struct vnode *vp; u_long flags; { - int error; struct mount *mp; struct vattr vattr; + int error; /* We can't support the value matching VNOVAL. */ if (flags == VNOVAL) @@ -2572,7 +2585,7 @@ setfflags(td, vp, flags) */ if (vp->v_type == VCHR || vp->v_type == VBLK) { error = priv_check(td, PRIV_VFS_CHFLAGS_DEV); - if (error) + if (error != 0) return (error); } @@ -2663,12 +2676,13 @@ kern_chflagsat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, u_long flags, int atflag) { struct nameidata nd; + cap_rights_t rights; int error, follow; AUDIT_ARG_FFLAGS(flags); follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd, - CAP_FCHFLAGS, td); + cap_rights_init(&rights, CAP_FCHFLAGS), td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2695,12 +2709,14 @@ sys_fchflags(td, uap) } */ *uap; { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); AUDIT_ARG_FFLAGS(uap->flags); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FCHFLAGS, - &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_FCHFLAGS), &fp); + if (error != 0) return (error); #ifdef AUDIT vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); @@ -2722,9 +2738,9 @@ setfmode(td, cred, vp, mode) struct vnode *vp; int mode; { - int error; struct mount *mp; struct vattr vattr; + int error; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); @@ -2817,14 +2833,14 @@ int kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, mode_t mode, int flag) { - int error; struct nameidata nd; - int follow; + cap_rights_t rights; + int error, follow; AUDIT_ARG_MODE(mode); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd, - CAP_FCHMOD, td); + cap_rights_init(&rights, CAP_FCHMOD), td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2846,12 +2862,13 @@ int sys_fchmod(struct thread *td, struct fchmod_args *uap) { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); AUDIT_ARG_MODE(uap->mode); - error = fget(td, uap->fd, CAP_FCHMOD, &fp); + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FCHMOD), &fp); if (error != 0) return (error); error = fo_chmod(fp, uap->mode, td->td_ucred, td); @@ -2870,9 +2887,9 @@ setfown(td, cred, vp, uid, gid) uid_t uid; gid_t gid; { - int error; struct mount *mp; struct vattr vattr; + int error; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); @@ -2949,12 +2966,13 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg, int uid, int gid, int flag) { struct nameidata nd; + cap_rights_t rights; int error, follow; AUDIT_ARG_OWNER(uid, gid); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd, - CAP_FCHOWN, td); + cap_rights_init(&rights, CAP_FCHOWN), td); if ((error = namei(&nd)) != 0) return (error); @@ -3016,11 +3034,12 @@ sys_fchown(td, uap) } */ *uap; { struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); AUDIT_ARG_OWNER(uap->uid, uap->gid); - error = fget(td, uap->fd, CAP_FCHOWN, &fp); + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FCHOWN), &fp); if (error != 0) return (error); error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td); @@ -3073,9 +3092,9 @@ setutimes(td, vp, ts, numtimes, nullflag) int numtimes; int nullflag; { - int error, setbirthtime; struct mount *mp; struct vattr vattr; + int error, setbirthtime; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); @@ -3155,12 +3174,13 @@ kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg, { struct nameidata nd; struct timespec ts[2]; + cap_rights_t rights; int error; if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd, - CAP_FUTIMES, td); + cap_rights_init(&rights, CAP_FUTIMES), td); if ((error = namei(&nd)) != 0) return (error); @@ -3197,8 +3217,8 @@ kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg) { struct timespec ts[2]; - int error; struct nameidata nd; + int error; if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); @@ -3238,12 +3258,16 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr, { struct timespec ts[2]; struct file *fp; + cap_rights_t rights; int error; AUDIT_ARG_FD(fd); - if ((error = getutimes(tptr, tptrseg, ts)) != 0) + error = getutimes(tptr, tptrseg, ts); + if (error != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_FUTIMES), &fp); + if (error != 0) return (error); #ifdef AUDIT vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); @@ -3390,13 +3414,17 @@ sys_fsync(td, uap) struct vnode *vp; struct mount *mp; struct file *fp; + cap_rights_t rights; int error, lock_flags; AUDIT_ARG_FD(uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_FSYNC), &fp); + if (error != 0) return (error); vp = fp->f_vnode; - if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) + error = vn_start_write(vp, &mp, V_WAIT | PCATCH); + if (error != 0) goto drop; if (MNT_SHARED_WRITES(mp) || ((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount))) { @@ -3472,15 +3500,17 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, struct mount *mp = NULL; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; + cap_rights_t rights; int error; bwillwrite(); #ifdef MAC NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | - AUDITVNODE1, pathseg, old, oldfd, CAP_RENAMEAT, td); + AUDITVNODE1, pathseg, old, oldfd, + cap_rights_init(&rights, CAP_RENAMEAT), td); #else NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1, - pathseg, old, oldfd, CAP_RENAMEAT, td); + pathseg, old, oldfd, cap_rights_init(&rights, CAP_RENAMEAT), td); #endif if ((error = namei(&fromnd)) != 0) @@ -3502,7 +3532,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, goto out1; } NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | - SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_LINKAT, td); + SAVESTART | AUDITVNODE2, pathseg, new, newfd, + cap_rights_init(&rights, CAP_LINKAT), td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -3531,8 +3562,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, * If the target already exists we require CAP_UNLINKAT * from 'newfd'. */ - error = cap_check(tond.ni_filecaps.fc_rights, - CAP_UNLINKAT); + error = cap_check(&tond.ni_filecaps.fc_rights, + cap_rights_init(&rights, CAP_UNLINKAT)); if (error != 0) goto out; } @@ -3554,15 +3585,15 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd); #endif out: - if (!error) { + if (error == 0) { error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, - tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); + tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); NDFREE(&fromnd, NDF_ONLY_PNBUF); NDFREE(&tond, NDF_ONLY_PNBUF); } else { NDFREE(&fromnd, NDF_ONLY_PNBUF); NDFREE(&tond, NDF_ONLY_PNBUF); - if (tvp) + if (tvp != NULL) vput(tvp); if (tdvp == tvp) vrele(tdvp); @@ -3630,14 +3661,15 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg, struct mount *mp; struct vnode *vp; struct vattr vattr; - int error; struct nameidata nd; + cap_rights_t rights; + int error; AUDIT_ARG_MODE(mode); restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - segflg, path, fd, CAP_MKDIRAT, td); + segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT), td); nd.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&nd)) != 0) return (error); @@ -3669,7 +3701,7 @@ restart: #ifdef MAC error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, &vattr); - if (error) + if (error != 0) goto out; #endif error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); @@ -3678,7 +3710,7 @@ out: #endif NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_dvp); - if (!error) + if (error == 0) vput(nd.ni_vp); vn_finished_write(mp); return (error); @@ -3715,13 +3747,14 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg) { struct mount *mp; struct vnode *vp; - int error; struct nameidata nd; + cap_rights_t rights; + int error; restart: bwillwrite(); NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1, - pathseg, path, fd, CAP_UNLINKAT, td); + pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -3746,7 +3779,7 @@ restart: #ifdef MAC error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp, &nd.ni_cnd); - if (error) + if (error != 0) goto out; #endif if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { @@ -3806,6 +3839,7 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, struct uio auio, kuio; struct iovec aiov, kiov; struct dirent *dp, *edp; + cap_rights_t rights; caddr_t dirbuf; int error, eofflag, readcnt; long loff; @@ -3814,7 +3848,9 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, uap->fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -3840,7 +3876,7 @@ unionread: loff = auio.uio_offset = foffset; #ifdef MAC error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error) { + if (error != 0) { VOP_UNLOCK(vp, 0); foffset_unlock(fp, foffset, FOF_NOUPDATE); fdrop(fp, td); @@ -3898,7 +3934,7 @@ unionread: } free(dirbuf, M_TEMP); } - if (error) { + if (error != 0) { VOP_UNLOCK(vp, 0); foffset_unlock(fp, foffset, 0); fdrop(fp, td); @@ -3952,7 +3988,7 @@ sys_getdirentries(td, uap) error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base, NULL, UIO_USERSPACE); - if (error) + if (error != 0) return (error); if (uap->basep != NULL) error = copyout(&base, uap->basep, sizeof(long)); @@ -3967,6 +4003,7 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, struct file *fp; struct uio auio; struct iovec aiov; + cap_rights_t rights; long loff; int error, eofflag; off_t foffset; @@ -3975,7 +4012,9 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, if (count > IOSIZE_MAX) return (EINVAL); auio.uio_resid = count; - if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ, &fp)) != 0) + error = getvnode(td->td_proc->p_fd, fd, + cap_rights_init(&rights, CAP_READ), &fp); + if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -4005,7 +4044,7 @@ unionread: error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); foffset = auio.uio_offset; - if (error) { + if (error != 0) { VOP_UNLOCK(vp, 0); goto fail; } @@ -4013,6 +4052,7 @@ unionread: (vp->v_vflag & VV_ROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) { struct vnode *tvp = vp; + vp = vp->v_mount->mnt_vnodecovered; VREF(vp); fp->f_vnode = vp; @@ -4049,6 +4089,7 @@ sys_getdents(td, uap) } */ *uap; { struct getdirentries_args ap; + ap.fd = uap->fd; ap.buf = uap->buf; ap.count = uap->count; @@ -4099,8 +4140,8 @@ sys_revoke(td, uap) { struct vnode *vp; struct vattr vattr; - int error; struct nameidata nd; + int error; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, uap->path, td); @@ -4114,15 +4155,15 @@ sys_revoke(td, uap) } #ifdef MAC error = mac_vnode_check_revoke(td->td_ucred, vp); - if (error) + if (error != 0) goto out; #endif error = VOP_GETATTR(vp, &vattr, td->td_ucred); - if (error) + if (error != 0) goto out; if (td->td_ucred->cr_uid != vattr.va_uid) { error = priv_check(td, PRIV_VFS_ADMIN); - if (error) + if (error != 0) goto out; } if (vcount(vp) > 1) @@ -4138,12 +4179,12 @@ out: * entry is held upon returning. */ int -getvnode(struct filedesc *fdp, int fd, cap_rights_t rights, struct file **fpp) +getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp) { struct file *fp; int error; - error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, rightsp, 0, &fp, NULL); if (error != 0) return (error); @@ -4188,12 +4229,12 @@ sys_lgetfh(td, uap) int error; error = priv_check(td, PRIV_VFS_GETFH); - if (error) + if (error != 0) return (error); NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, uap->fname, td); error = namei(&nd); - if (error) + if (error != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; @@ -4201,9 +4242,8 @@ sys_lgetfh(td, uap) fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; error = VOP_VPTOFH(vp, &fh.fh_fid); vput(vp); - if (error) - return (error); - error = copyout(&fh, uap->fhp, sizeof (fh)); + if (error == 0) + error = copyout(&fh, uap->fhp, sizeof (fh)); return (error); } @@ -4224,12 +4264,12 @@ sys_getfh(td, uap) int error; error = priv_check(td, PRIV_VFS_GETFH); - if (error) + if (error != 0) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, uap->fname, td); error = namei(&nd); - if (error) + if (error != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; @@ -4237,9 +4277,8 @@ sys_getfh(td, uap) fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; error = VOP_VPTOFH(vp, &fh.fh_fid); vput(vp); - if (error) - return (error); - error = copyout(&fh, uap->fhp, sizeof (fh)); + if (error == 0) + error = copyout(&fh, uap->fhp, sizeof (fh)); return (error); } @@ -4272,7 +4311,7 @@ sys_fhopen(td, uap) int indx; error = priv_check(td, PRIV_VFS_FHOPEN); - if (error) + if (error != 0) return (error); indx = -1; fmode = FFLAGS(uap->flags); @@ -4280,7 +4319,7 @@ sys_fhopen(td, uap) if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) return (EINVAL); error = copyin(uap->u_fhp, &fhp, sizeof(fhp)); - if (error) + if (error != 0) return(error); /* find the mount point */ mp = vfs_busyfs(&fhp.fh_fsid); @@ -4289,11 +4328,11 @@ sys_fhopen(td, uap) /* now give me my vnode, it gets returned to me locked */ error = VFS_FHTOVP(mp, &fhp.fh_fid, LK_EXCLUSIVE, &vp); vfs_unbusy(mp); - if (error) + if (error != 0) return (error); error = falloc_noinstall(td, &fp); - if (error) { + if (error != 0) { vput(vp); return (error); } @@ -4306,7 +4345,7 @@ sys_fhopen(td, uap) td->td_dupfd = -1; #endif error = vn_open_vnode(vp, fmode, td->td_ucred, td, fp); - if (error) { + if (error != 0) { KASSERT(fp->f_ops == &badfileops, ("VOP_OPEN in fhopen() set f_ops")); KASSERT(td->td_dupfd < 0, @@ -4323,9 +4362,9 @@ sys_fhopen(td, uap) finit(fp, (fmode & FMASK) | (fp->f_flag & FHASLOCK), DTYPE_VNODE, vp, &vnops); VOP_UNLOCK(vp, 0); - if (fmode & O_TRUNC) { + if ((fmode & O_TRUNC) != 0) { error = fo_truncate(fp, 0, td->td_ucred, td); - if (error) + if (error != 0) goto bad; } @@ -4361,9 +4400,8 @@ sys_fhstat(td, uap) if (error != 0) return (error); error = kern_fhstat(td, fh, &sb); - if (error != 0) - return (error); - error = copyout(&sb, uap->sb, sizeof(sb)); + if (error == 0) + error = copyout(&sb, uap->sb, sizeof(sb)); return (error); } @@ -4375,13 +4413,13 @@ kern_fhstat(struct thread *td, struct fhandle fh, struct stat *sb) int error; error = priv_check(td, PRIV_VFS_FHSTAT); - if (error) + if (error != 0) return (error); if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL) return (ESTALE); error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp); vfs_unbusy(mp); - if (error) + if (error != 0) return (error); error = vn_stat(vp, sb, td->td_ucred, NOCRED, td); vput(vp); @@ -4410,10 +4448,10 @@ sys_fhstatfs(td, uap) int error; error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); - if (error) + if (error != 0) return (error); error = kern_fhstatfs(td, fh, &sf); - if (error) + if (error != 0) return (error); return (copyout(&sf, uap->buf, sizeof(sf))); } @@ -4427,22 +4465,22 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) int error; error = priv_check(td, PRIV_VFS_FHSTATFS); - if (error) + if (error != 0) return (error); if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL) return (ESTALE); error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp); - if (error) { + if (error != 0) { vfs_unbusy(mp); return (error); } vput(vp); error = prison_canseemount(td->td_ucred, mp); - if (error) + if (error != 0) goto out; #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); - if (error) + if (error != 0) goto out; #endif /* @@ -4466,11 +4504,12 @@ kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) struct file *fp; struct mount *mp; struct vnode *vp; + cap_rights_t rights; off_t olen, ooffset; int error; fp = NULL; - error = fget(td, fd, CAP_WRITE, &fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_WRITE), &fp); if (error != 0) goto out; @@ -4562,6 +4601,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, struct fadvise_info *fa, *new; struct file *fp; struct vnode *vp; + cap_rights_t rights; off_t end; int error; @@ -4582,7 +4622,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, return (EINVAL); } /* XXX: CAP_POSIX_FADVISE? */ - error = fget(td, fd, CAP_NONE, &fp); + error = fget(td, fd, cap_rights_init(&rights), &fp); if (error != 0) goto out; diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c index 21b945f..aabab52 100644 --- a/sys/mips/atheros/if_arge.c +++ b/sys/mips/atheros/if_arge.c @@ -142,6 +142,7 @@ static int arge_resume(device_t); static int arge_rx_ring_init(struct arge_softc *); static void arge_rx_ring_free(struct arge_softc *sc); static int arge_tx_ring_init(struct arge_softc *); +static void arge_tx_ring_free(struct arge_softc *); #ifdef DEVICE_POLLING static int arge_poll(struct ifnet *, enum poll_cmd, int); #endif @@ -1278,6 +1279,7 @@ arge_stop(struct arge_softc *sc) /* Flush FIFO and free any existing mbufs */ arge_flush_ddr(sc); arge_rx_ring_free(sc); + arge_tx_ring_free(sc); } @@ -1708,6 +1710,30 @@ arge_tx_ring_init(struct arge_softc *sc) } /* + * Free the Tx ring, unload any pending dma transaction and free the mbuf. + */ +static void +arge_tx_ring_free(struct arge_softc *sc) +{ + struct arge_txdesc *txd; + int i; + + /* Free the Tx buffers. */ + for (i = 0; i < ARGE_TX_RING_COUNT; i++) { + txd = &sc->arge_cdata.arge_txdesc[i]; + if (txd->tx_dmamap) { + bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, + txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, + txd->tx_dmamap); + } + if (txd->tx_m) + m_freem(txd->tx_m); + txd->tx_m = NULL; + } +} + +/* * Initialize the RX descriptors and allocate mbufs for them. Note that * we arrange the descriptors in a closed ring, so that the last descriptor * points back to the first. diff --git a/sys/mips/conf/DIR-825 b/sys/mips/conf/DIR-825 index 62189cfc..7740d4d 100644 --- a/sys/mips/conf/DIR-825 +++ b/sys/mips/conf/DIR-825 @@ -54,12 +54,15 @@ options NO_SYSCTL_DESCR device geom_map # to get access to the SPI flash partitions device geom_uncompress # compressed in-memory filesystem hackery! options GEOM_UNCOMPRESS +options GEOM_PART_GPT options ROOTDEVNAME=\"ufs:/dev/map/rootfs.uncompress\" options AR71XX_REALMEM=64*1024*1024 options AR71XX_ENV_UBOOT +options MSDOSFS # Read MSDOS filesystems; useful for USB/CF + # options MD_ROOT # options MD_ROOT_SIZE="6144" diff --git a/sys/mips/conf/GXEMUL32 b/sys/mips/conf/GXEMUL32 new file mode 100644 index 0000000..6bd756f --- /dev/null +++ b/sys/mips/conf/GXEMUL32 @@ -0,0 +1,61 @@ +# +# GXEMUL "oldtestmips" sample kernel configuration. +# +# $FreeBSD$ +# + +ident GXEMUL + +machine mips mips +cpu CPU_MIPS4KC + +options HZ=100 + +makeoptions KERNLOADADDR=0x80100000 + +include "../gxemul/std.gxemul" + +hints "GXEMUL.hints" #Default places to look for devices. + +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols + +makeoptions MODULES_OVERRIDE="" + +options DDB +options KDB + +# Make an SMP-capable kernel by default +options SMP # Symmetric MultiProcessor Kernel + +options SCHED_ULE +options INET # InterNETworking +options INET6 # IPv6 communications protocols + +options FFS #Berkeley Fast Filesystem + +# Debugging for use in -current +#options DEADLKRES #Enable the deadlock resolver +options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS #Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed + +options ROOTDEVNAME=\"ufs:gxemul_disk0\" + +device gxemul_cons +device gxemul_disk +device gxemul_ether + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +device tun # Packet tunnel. +device md # Memory "disks" +device gif # IPv6 and IPv4 tunneling +device faith # IPv6-to-IPv4 relaying (translation) + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf # Berkeley packet filter diff --git a/sys/mips/gxemul/mpreg.h b/sys/mips/gxemul/mpreg.h index e09946d..f562d07 100644 --- a/sys/mips/gxemul/mpreg.h +++ b/sys/mips/gxemul/mpreg.h @@ -43,10 +43,17 @@ #define GXEMUL_MP_DEV_IPI_READ 0x00c0 #define GXEMUL_MP_DEV_CYCLES 0x00d0 +#ifdef _LP64 #define GXEMUL_MP_DEV_FUNCTION(f) \ (volatile uint64_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_MP_DEV_BASE + (f)) #define GXEMUL_MP_DEV_READ(f) \ (volatile uint64_t)*GXEMUL_MP_DEV_FUNCTION(f) +#else +#define GXEMUL_MP_DEV_FUNCTION(f) \ + (volatile uint32_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_MP_DEV_BASE + (f)) +#define GXEMUL_MP_DEV_READ(f) \ + (volatile uint32_t)*GXEMUL_MP_DEV_FUNCTION(f) +#endif #define GXEMUL_MP_DEV_WRITE(f, v) \ *GXEMUL_MP_DEV_FUNCTION(f) = (v) diff --git a/sys/mips/include/_stdint.h b/sys/mips/include/_stdint.h index 510b8ea..ebf6eb5 100644 --- a/sys/mips/include/_stdint.h +++ b/sys/mips/include/_stdint.h @@ -66,6 +66,7 @@ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) +#ifndef __INT64_C #ifdef __mips_n64 #define __INT64_C(c) (c ## L) #define __UINT64_C(c) (c ## UL) @@ -73,6 +74,7 @@ #define __INT64_C(c) (c ## LL) #define __UINT64_C(c) (c ## ULL) #endif +#endif /* * ISO/IEC 9899:1999 diff --git a/sys/mips/include/sf_buf.h b/sys/mips/include/sf_buf.h index b9efaf0..00502a0 100644 --- a/sys/mips/include/sf_buf.h +++ b/sys/mips/include/sf_buf.h @@ -41,6 +41,18 @@ /* In 64 bit the whole memory is directly mapped */ struct sf_buf; +static inline struct sf_buf * +sf_buf_alloc(struct vm_page *m, int pri) +{ + + return ((struct sf_buf *)m); +} + +static inline void +sf_buf_free(struct sf_buf *sf) +{ +} + static __inline vm_offset_t sf_buf_kva(struct sf_buf *sf) { diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index ebb6935..d1bf5ea 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -1914,7 +1914,6 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) if (prot & VM_PROT_WRITE) return; - rw_wlock(&pvh_global_lock); PMAP_LOCK(pmap); for (; sva < eva; sva = va_next) { pdpe = pmap_segmap(pmap, sva); @@ -1980,7 +1979,6 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) if (va != va_next) pmap_invalidate_range(pmap, va, sva); } - rw_wunlock(&pvh_global_lock); PMAP_UNLOCK(pmap); } diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c index 86dfde9..c42f640 100644 --- a/sys/mips/mips/vm_machdep.c +++ b/sys/mips/mips/vm_machdep.c @@ -76,7 +76,9 @@ __FBSDID("$FreeBSD$"); #include <sys/user.h> #include <sys/mbuf.h> +#ifndef __mips_n64 #include <sys/sf_buf.h> +#endif #ifndef NSFBUFS #define NSFBUFS (512 + maxusers * 16) @@ -523,7 +525,6 @@ sf_buf_init(void *arg) } sf_buf_alloc_want = 0; } -#endif /* * Get an sf_buf from the freelist. Will block if none are available. @@ -531,7 +532,6 @@ sf_buf_init(void *arg) struct sf_buf * sf_buf_alloc(struct vm_page *m, int flags) { -#ifndef __mips_n64 struct sf_buf *sf; int error; @@ -560,9 +560,6 @@ sf_buf_alloc(struct vm_page *m, int flags) } mtx_unlock(&sf_freelist.sf_lock); return (sf); -#else - return ((struct sf_buf *)m); -#endif } /* @@ -571,7 +568,6 @@ sf_buf_alloc(struct vm_page *m, int flags) void sf_buf_free(struct sf_buf *sf) { -#ifndef __mips_n64 pmap_qremove(sf->kva, 1); mtx_lock(&sf_freelist.sf_lock); SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); @@ -579,8 +575,8 @@ sf_buf_free(struct sf_buf *sf) if (sf_buf_alloc_want > 0) wakeup(&sf_freelist); mtx_unlock(&sf_freelist.sf_lock); -#endif } +#endif /* !__mips_n64 */ /* * Software interrupt handler for queued VM system processing. diff --git a/sys/modules/aesni/Makefile b/sys/modules/aesni/Makefile index 9e25a46..26dbedc 100644 --- a/sys/modules/aesni/Makefile +++ b/sys/modules/aesni/Makefile @@ -3,8 +3,17 @@ .PATH: ${.CURDIR}/../../crypto/aesni KMOD= aesni -SRCS= aesni.c aesni_wrap.c -SRCS+= aesencdec_${MACHINE_CPUARCH}.S aeskeys_${MACHINE_CPUARCH}.S +SRCS= aesni.c +SRCS+= aeskeys_${MACHINE_CPUARCH}.S SRCS+= device_if.h bus_if.h opt_bus.h cryptodev_if.h +OBJS+= aesni_wrap.o + +# Remove -nostdinc so we can get the intrinsics. +aesni_wrap.o: aesni_wrap.c + ${CC} -c ${CFLAGS:C/^-O2$/-O3/:N-nostdinc} ${WERROR} ${PROF} \ + -mmmx -msse -maes ${.IMPSRC} + ${CTFCONVERT_CMD} + .include <bsd.kmod.mk> + diff --git a/sys/modules/cam/Makefile b/sys/modules/cam/Makefile index c2dec72..c3ecf56 100644 --- a/sys/modules/cam/Makefile +++ b/sys/modules/cam/Makefile @@ -13,6 +13,7 @@ SRCS+= opt_scsi.h SRCS+= opt_cd.h SRCS+= opt_pt.h SRCS+= opt_sa.h +SRCS+= opt_ses.h SRCS+= device_if.h bus_if.h vnode_if.h SRCS+= cam.c SRCS+= cam_compat.c diff --git a/sys/modules/hwpmc/Makefile b/sys/modules/hwpmc/Makefile index 8948805..0ebf7a1 100644 --- a/sys/modules/hwpmc/Makefile +++ b/sys/modules/hwpmc/Makefile @@ -29,7 +29,7 @@ SRCS+= hwpmc_ia64.c .endif .if ${MACHINE_CPUARCH} == "powerpc" -SRCS+= hwpmc_powerpc.c +SRCS+= hwpmc_powerpc.c hwpmc_mpc7xxx.c .endif .if ${MACHINE_CPUARCH} == "sparc64" diff --git a/sys/modules/send/Makefile b/sys/modules/send/Makefile index 1cb976b..06ea9e0 100644 --- a/sys/modules/send/Makefile +++ b/sys/modules/send/Makefile @@ -2,6 +2,6 @@ .PATH: ${.CURDIR}/../../netinet6 KMOD= send -SRCS= send.c +SRCS= send.c opt_kdtrace.h .include <bsd.kmod.mk> diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c index 2009cca..edbd32c 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c @@ -494,6 +494,7 @@ static const STRUCT_USB_HOST_ID ubt_devs[] = /* Broadcom BCM20702A0 */ { USB_VPI(USB_VENDOR_ASUS, 0x17b5, 0) }, + { USB_VPI(USB_VENDOR_ASUS, 0x17cb, 0) }, { USB_VPI(USB_VENDOR_LITEON, 0x2003, 0) }, { USB_VPI(USB_VENDOR_FOXCONN, 0xe042, 0) }, { USB_VPI(USB_VENDOR_DELL, 0x8197, 0) }, diff --git a/sys/netgraph/netflow/ng_netflow.h b/sys/netgraph/netflow/ng_netflow.h index 875a75d..0d708b7 100644 --- a/sys/netgraph/netflow/ng_netflow.h +++ b/sys/netgraph/netflow/ng_netflow.h @@ -416,7 +416,7 @@ struct netflow { * indexed by hash hash. Each hash element consist of tailqueue * head and mutex to protect this element. */ -#define CACHESIZE (65536*4) +#define CACHESIZE (65536*16) #define CACHELOWAT (CACHESIZE * 3/4) #define CACHEHIGHWAT (CACHESIZE * 9/10) uma_zone_t zone; diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 23f1be7..3a03def 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -609,7 +609,7 @@ static void if_detached_event(void *arg __unused, struct ifnet *ifp) { vifi_t vifi; - int i; + u_long i; MROUTER_LOCK(); @@ -634,8 +634,8 @@ if_detached_event(void *arg __unused, struct ifnet *ifp) continue; for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); + + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { if (rt->mfc_parent == vifi) { expire_mfc(rt); } @@ -704,10 +704,9 @@ ip_mrouter_init(struct socket *so, int version) static int X_ip_mrouter_done(void) { - vifi_t vifi; - int i; struct ifnet *ifp; - struct ifreq ifr; + u_long i; + vifi_t vifi; MROUTER_LOCK(); @@ -732,11 +731,6 @@ X_ip_mrouter_done(void) for (vifi = 0; vifi < V_numvifs; vifi++) { if (!in_nullhost(V_viftable[vifi].v_lcl_addr) && !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { - struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr); - - so->sin_len = sizeof(struct sockaddr_in); - so->sin_family = AF_INET; - so->sin_addr.s_addr = INADDR_ANY; ifp = V_viftable[vifi].v_ifp; if_allmulti(ifp, 0); } @@ -759,8 +753,8 @@ X_ip_mrouter_done(void) */ for (i = 0; i < mfchashsize; i++) { struct mfc *rt, *nrt; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); + + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { expire_mfc(rt); } } @@ -803,7 +797,7 @@ set_assert(int i) int set_api_config(uint32_t *apival) { - int i; + u_long i; /* * We can set the API capabilities only if it is the first operation @@ -1439,7 +1433,7 @@ non_fatal: static void expire_upcalls(void *arg) { - int i; + u_long i; CURVNET_SET((struct vnet *) arg); @@ -1451,9 +1445,7 @@ expire_upcalls(void *arg) if (V_nexpire[i] == 0) continue; - for (rt = LIST_FIRST(&V_mfchashtbl[i]); rt; rt = nrt) { - nrt = LIST_NEXT(rt, mfc_hash); - + LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { if (TAILQ_EMPTY(&rt->mfc_stall)) continue; diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index 42e2636..0048856 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -703,15 +703,7 @@ sctp_auth_add_hmacid(sctp_hmaclist_t * list, uint16_t hmac_id) return (-1); } if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) && -#ifdef HAVE_SHA224 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA224) && -#endif -#ifdef HAVE_SHA2 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA256) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA384) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA512) && -#endif - 1) { + (hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) { return (-1); } /* Now is it already in the list */ @@ -754,8 +746,9 @@ sctp_default_supported_hmaclist(void) new_list = sctp_alloc_hmaclist(2); if (new_list == NULL) return (NULL); - (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1); + /* We prefer SHA256, so list it first */ (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256); + (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1); return (new_list); } @@ -811,19 +804,13 @@ int sctp_verify_hmac_param(struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs) { uint32_t i; - uint16_t hmac_id; - uint32_t sha1_supported = 0; for (i = 0; i < num_hmacs; i++) { - hmac_id = ntohs(hmacs->hmac_ids[i]); - if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1) - sha1_supported = 1; + if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) { + return (0); + } } - /* all HMAC id's are supported */ - if (sha1_supported == 0) - return (-1); - else - return (0); + return (-1); } sctp_authinfo_t * @@ -877,18 +864,8 @@ sctp_get_hmac_digest_len(uint16_t hmac_algo) switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: return (SCTP_AUTH_DIGEST_LEN_SHA1); -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - return (SCTP_AUTH_DIGEST_LEN_SHA224); -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: return (SCTP_AUTH_DIGEST_LEN_SHA256); - case SCTP_AUTH_HMAC_ID_SHA384: - return (SCTP_AUTH_DIGEST_LEN_SHA384); - case SCTP_AUTH_HMAC_ID_SHA512: - return (SCTP_AUTH_DIGEST_LEN_SHA512); -#endif default: /* unknown HMAC algorithm: can't do anything */ return (0); @@ -900,17 +877,9 @@ sctp_get_hmac_block_len(uint16_t hmac_algo) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: -#endif return (64); -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: return (64); - case SCTP_AUTH_HMAC_ID_SHA384: - case SCTP_AUTH_HMAC_ID_SHA512: - return (128); -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -923,23 +892,11 @@ sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t * ctx) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Init(&ctx->sha1); - break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: + SCTP_SHA1_INIT(&ctx->sha1); break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Init(&ctx->sha256); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Init(&ctx->sha384); + SCTP_SHA256_INIT(&ctx->sha256); break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Init(&ctx->sha512); - break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -953,23 +910,11 @@ sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t * ctx, { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Update(&ctx->sha1, text, textlen); + SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Update(&ctx->sha256, text, textlen); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Update(&ctx->sha384, text, textlen); + SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen); break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Update(&ctx->sha512, text, textlen); - break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -983,24 +928,11 @@ sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t * ctx, { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Final(digest, &ctx->sha1); + SCTP_SHA1_FINAL(digest, &ctx->sha1); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Final(digest, &ctx->sha256); + SCTP_SHA256_FINAL(digest, &ctx->sha256); break; - case SCTP_AUTH_HMAC_ID_SHA384: - /* SHA384 is truncated SHA512 */ - SHA384_Final(digest, &ctx->sha384); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Final(digest, &ctx->sha512); - break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ diff --git a/sys/netinet/sctp_auth.h b/sys/netinet/sctp_auth.h index eac89f6..154bc13 100644 --- a/sys/netinet/sctp_auth.h +++ b/sys/netinet/sctp_auth.h @@ -36,14 +36,12 @@ __FBSDID("$FreeBSD$"); #ifndef _NETINET_SCTP_AUTH_H_ #define _NETINET_SCTP_AUTH_H_ +#include <netinet/sctp_os.h> /* digest lengths */ #define SCTP_AUTH_DIGEST_LEN_SHA1 20 -#define SCTP_AUTH_DIGEST_LEN_SHA224 28 #define SCTP_AUTH_DIGEST_LEN_SHA256 32 -#define SCTP_AUTH_DIGEST_LEN_SHA384 48 -#define SCTP_AUTH_DIGEST_LEN_SHA512 64 -#define SCTP_AUTH_DIGEST_LEN_MAX 64 +#define SCTP_AUTH_DIGEST_LEN_MAX SCTP_AUTH_DIGEST_LEN_SHA256 /* random sizes */ #define SCTP_AUTH_RANDOM_SIZE_DEFAULT 32 @@ -52,12 +50,8 @@ __FBSDID("$FreeBSD$"); /* union of all supported HMAC algorithm contexts */ typedef union sctp_hash_context { - SHA1_CTX sha1; -#ifdef HAVE_SHA2 - SHA256_CTX sha256; - SHA384_CTX sha384; - SHA512_CTX sha512; -#endif + SCTP_SHA1_CTX sha1; + SCTP_SHA256_CTX sha256; } sctp_hash_context_t; typedef struct sctp_key { diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index dc5b7e1..7ebf7f1 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4718,7 +4718,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, } } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - if (tp1->pr_sctp_on) { + if (PR_SCTP_ENABLED(tp1->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 252ea93..2159bbc 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -104,6 +104,9 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_options.h> +#include <crypto/sha1.h> +#include <crypto/sha2/sha2.h> + #ifndef in6pcb #define in6pcb inpcb #endif @@ -468,23 +471,18 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, /* * SCTP AUTH */ -#define HAVE_SHA2 - #define SCTP_READ_RANDOM(buf, len) read_random(buf, len) -#ifdef USE_SCTP_SHA1 -#include <netinet/sctp_sha1.h> -#else -#include <crypto/sha1.h> /* map standard crypto API names */ -#define SHA1_Init SHA1Init -#define SHA1_Update SHA1Update -#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y) -#endif - -#if defined(HAVE_SHA2) -#include <crypto/sha2/sha2.h> -#endif +#define SCTP_SHA1_CTX SHA1_CTX +#define SCTP_SHA1_INIT SHA1Init +#define SCTP_SHA1_UPDATE SHA1Update +#define SCTP_SHA1_FINAL(x,y) SHA1Final((caddr_t)x, y) + +#define SCTP_SHA256_CTX SHA256_CTX +#define SCTP_SHA256_INIT SHA256_Init +#define SCTP_SHA256_UPDATE SHA256_Update +#define SCTP_SHA256_FINAL(x,y) SHA256_Final((caddr_t)x, y) #endif diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 50e1ed9..3d76b7e 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3561,7 +3561,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er static struct sctp_tcb * sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, - in_port_t port, + uint16_t port, struct mbuf *control, struct sctp_nets **net_p, int *error) @@ -6067,7 +6067,6 @@ sctp_get_frag_point(struct sctp_tcb *stcb, static void sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp) { - sp->pr_sctp_on = 0; /* * We assume that the user wants PR_SCTP_TTL if the user provides a * positive lifetime but does not specify any PR_SCTP policy. This @@ -6077,7 +6076,6 @@ sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp) */ if (PR_SCTP_ENABLED(sp->sinfo_flags)) { sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags); - sp->pr_sctp_on = 1; } else { return; } @@ -7425,13 +7423,8 @@ dont_do_it: } chk->send_size += pads; } - /* We only re-set the policy if it is on */ - if (sp->pr_sctp_on) { - sctp_set_prsctp_policy(sp); + if (PR_SCTP_ENABLED(chk->flags)) { asoc->pr_sctp_cnt++; - chk->pr_sctp_on = 1; - } else { - chk->pr_sctp_on = 0; } if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) { /* All done pull and kill the message */ diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 508e0e1..a8b86c6 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -446,7 +446,6 @@ struct sctp_tmit_chunk { uint8_t do_rtt; uint8_t book_size_scale; uint8_t no_fr_allowed; - uint8_t pr_sctp_on; uint8_t copy_by_ref; uint8_t window_probe; }; @@ -522,7 +521,6 @@ struct sctp_stream_queue_pending { uint8_t holds_key_ref; uint8_t msg_is_complete; uint8_t some_taken; - uint8_t pr_sctp_on; uint8_t sender_all_done; uint8_t put_last_out; uint8_t discard_rest; diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index a09ba34..833c94a 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -446,7 +446,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) } } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); - if (chk->pr_sctp_on) { + if (PR_SCTP_ENABLED(chk->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index d482c61..1295391 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -662,10 +662,6 @@ struct sctp_hmacalgo { #define SCTP_AUTH_HMAC_ID_RSVD 0x0000 #define SCTP_AUTH_HMAC_ID_SHA1 0x0001 /* default, mandatory */ #define SCTP_AUTH_HMAC_ID_SHA256 0x0003 -#define SCTP_AUTH_HMAC_ID_SHA224 0x0004 -#define SCTP_AUTH_HMAC_ID_SHA384 0x0005 -#define SCTP_AUTH_HMAC_ID_SHA512 0x0006 - /* SCTP_AUTH_ACTIVE_KEY / SCTP_AUTH_DELETE_KEY */ struct sctp_authkeyid { diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index bdc3c90..c101118 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -4833,7 +4833,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, atomic_add_int(&chk->whoTo->ref_count, 1); chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); stcb->asoc.pr_sctp_cnt++; - chk->pr_sctp_on = 1; TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); stcb->asoc.sent_queue_cnt++; stcb->asoc.pr_sctp_cnt++; diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index 9634636..36d0d6f 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -576,7 +576,7 @@ int X_ip6_mrouter_done(void) { mifi_t mifi; - int i; + u_long i; struct mf6c *rt; struct rtdetq *rte; @@ -1341,7 +1341,7 @@ expire_upcalls(void *unused) { struct rtdetq *rte; struct mf6c *mfc, **nptr; - int i; + u_long i; MFC6_LOCK(); for (i = 0; i < MF6CTBLSIZ; i++) { diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c index c82a121..f870bf4 100644 --- a/sys/netpfil/pf/pf_lb.c +++ b/sys/netpfil/pf/pf_lb.c @@ -58,10 +58,9 @@ static struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, int, int, struct pfi_kif *, struct pf_addr *, u_int16_t, struct pf_addr *, uint16_t, int, struct pf_anchor_stackframe *); -static int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *, - struct pf_addr *, struct pf_addr *, u_int16_t, - struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t, - struct pf_src_node **); +static int pf_get_sport(sa_family_t, uint8_t, struct pf_rule *, + struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *, + uint16_t *, uint16_t, uint16_t, struct pf_src_node **); #define mix(a,b,c) \ do { \ @@ -210,13 +209,13 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, static int pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, - struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport, - struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high, - struct pf_src_node **sn) + struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr, + uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low, + uint16_t high, struct pf_src_node **sn) { struct pf_state_key_cmp key; struct pf_addr init_addr; - u_int16_t cut; + uint16_t cut; bzero(&init_addr, sizeof(init_addr)); if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) @@ -227,34 +226,38 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, high = 65535; } + bzero(&key, sizeof(key)); + key.af = af; + key.proto = proto; + key.port[0] = dport; + PF_ACPY(&key.addr[0], daddr, key.af); + do { - key.af = af; - key.proto = proto; - PF_ACPY(&key.addr[1], daddr, key.af); - PF_ACPY(&key.addr[0], naddr, key.af); - key.port[1] = dport; + PF_ACPY(&key.addr[1], naddr, key.af); /* * port search; start random, step; * similar 2 portloop in in_pcbbind */ if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP || - proto == IPPROTO_ICMP)) { - key.port[0] = dport; - if (pf_find_state_all(&key, PF_IN, NULL) == NULL) - return (0); - } else if (low == 0 && high == 0) { - key.port[0] = *nport; - if (pf_find_state_all(&key, PF_IN, NULL) == NULL) + proto == IPPROTO_ICMP) || (low == 0 && high == 0)) { + /* + * XXX bug: icmp states don't use the id on both sides. + * (traceroute -I through nat) + */ + key.port[1] = sport; + if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { + *nport = sport; return (0); + } } else if (low == high) { - key.port[0] = htons(low); + key.port[1] = htons(low); if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(low); return (0); } } else { - u_int16_t tmp; + uint16_t tmp; if (low > high) { tmp = low; @@ -265,7 +268,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, cut = htonl(arc4random()) % (1 + high - low) + low; /* low <= cut <= high */ for (tmp = cut; tmp <= high; ++(tmp)) { - key.port[0] = htons(tmp); + key.port[1] = htons(tmp); if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(tmp); @@ -273,7 +276,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, } } for (tmp = cut - 1; tmp >= low; --(tmp)) { - key.port[0] = htons(tmp); + key.port[1] = htons(tmp); if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(tmp); @@ -551,8 +554,8 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, switch (r->action) { case PF_NAT: - if (pf_get_sport(pd->af, pd->proto, r, saddr, daddr, dport, - naddr, nport, r->rpool.proxy_port[0], + if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr, + dport, naddr, nport, r->rpool.proxy_port[0], r->rpool.proxy_port[1], sn)) { DPFPRINTF(PF_DEBUG_MISC, ("pf: NAT proxy port allocation (%u-%u) failed\n", diff --git a/sys/netsmb/smb_dev.c b/sys/netsmb/smb_dev.c index 0efb282..279ae67 100644 --- a/sys/netsmb/smb_dev.c +++ b/sys/netsmb/smb_dev.c @@ -378,6 +378,7 @@ int smb_dev2share(int fd, int mode, struct smb_cred *scred, struct smb_share **sspp, struct smb_dev **ssdp) { + cap_rights_t rights; struct file *fp, *fptmp; struct smb_dev *sdp; struct smb_share *ssp; @@ -385,7 +386,7 @@ smb_dev2share(int fd, int mode, struct smb_cred *scred, int error; td = curthread; - error = fget(td, fd, CAP_READ, &fp); + error = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp); if (error) return (error); fptmp = td->td_fpop; diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c index db69df9..85003b7 100644 --- a/sys/nfsserver/nfs_srvkrpc.c +++ b/sys/nfsserver/nfs_srvkrpc.c @@ -168,6 +168,7 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap) struct file *fp; struct nfsd_addsock_args addsockarg; struct nfsd_nfsd_args nfsdarg; + cap_rights_t rights; int error; if (uap->flag & NFSSVC_ADDSOCK) { @@ -175,7 +176,8 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap) sizeof(addsockarg)); if (error) return (error); - error = fget(td, addsockarg.sock, CAP_SOCK_SERVER, &fp); + error = fget(td, addsockarg.sock, + cap_rights_init(&rights, CAP_SOCK_SERVER), &fp); if (error) return (error); if (fp->f_type != DTYPE_SOCKET) { diff --git a/sys/ofed/include/linux/file.h b/sys/ofed/include/linux/file.h index b9bd8b1..bb9d58d 100644 --- a/sys/ofed/include/linux/file.h +++ b/sys/ofed/include/linux/file.h @@ -47,8 +47,10 @@ linux_fget(unsigned int fd) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { return (NULL); + } return (struct linux_file *)file->f_data; } @@ -70,8 +72,10 @@ put_unused_fd(unsigned int fd) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { return; + } fdclose(curthread->td_proc->p_fd, file, fd, curthread); } @@ -80,8 +84,10 @@ fd_install(unsigned int fd, struct linux_file *filp) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { file = NULL; + } filp->_file = file; finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); } diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 97f4ca1..2edbbfa 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -197,13 +197,11 @@ trap(struct trapframe *frame) #ifdef HWPMC_HOOKS if (type == EXC_PERF && (pmc_intr != NULL)) { -#ifdef notyet - (*pmc_intr)(PCPU_GET(cpuid), frame); - if (!user) + (*pmc_intr)(PCPU_GET(cpuid), frame); + if (user) + userret(td, frame); return; -#endif } - else #endif #ifdef KDTRACE_HOOKS /* @@ -316,9 +314,11 @@ trap(struct trapframe *frame) if (*(uintptr_t *)frame->srr0 == 0x7c810808) { if (dtrace_invop_jump_addr != NULL) { dtrace_invop_jump_addr(frame); + return; } } } + break; #endif #ifdef __powerpc64__ case EXC_DSE: diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c index 2deb4cb..1790ce3 100644 --- a/sys/powerpc/aim/vm_machdep.c +++ b/sys/powerpc/aim/vm_machdep.c @@ -187,6 +187,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) cf->cf_arg1 = (register_t)tf; pcb->pcb_sp = (register_t)cf; + KASSERT(pcb->pcb_sp % 16 == 0, ("stack misaligned")); #ifdef __powerpc64__ pcb->pcb_lr = ((register_t *)fork_trampoline)[0]; pcb->pcb_toc = ((register_t *)fork_trampoline)[1]; diff --git a/sys/powerpc/include/_stdint.h b/sys/powerpc/include/_stdint.h index 6ad1fd2..9928a1a 100644 --- a/sys/powerpc/include/_stdint.h +++ b/sys/powerpc/include/_stdint.h @@ -65,6 +65,7 @@ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) +#ifndef __INT64_C #ifdef __LP64__ #define __INT64_C(c) (c ## L) #define __UINT64_C(c) (c ## UL) @@ -72,6 +73,7 @@ #define __INT64_C(c) (c ## LL) #define __UINT64_C(c) (c ## ULL) #endif +#endif /* * ISO/IEC 9899:1999 diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h index 196cb6f..d2100a1 100644 --- a/sys/powerpc/include/frame.h +++ b/sys/powerpc/include/frame.h @@ -94,6 +94,7 @@ struct callframe { register_t cf_func; register_t cf_arg0; register_t cf_arg1; + register_t _padding; /* Maintain 16-byte alignment */ }; #else struct callframe { @@ -102,6 +103,7 @@ struct callframe { register_t cf_func; register_t cf_arg0; register_t cf_arg1; + register_t _padding; /* Maintain 16-byte alignment */ }; #endif diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h index 3456368..678852b 100644 --- a/sys/powerpc/include/pmc_mdep.h +++ b/sys/powerpc/include/pmc_mdep.h @@ -7,7 +7,8 @@ #ifndef _MACHINE_PMC_MDEP_H_ #define _MACHINE_PMC_MDEP_H_ -#define PMC_MDEP_CLASS_INDEX_PPC7450 1 +#define PMC_MDEP_CLASS_INDEX_PPC7450 0 +#define PMC_MDEP_CLASS_INDEX_PPC970 0 union pmc_md_op_pmcallocate { uint64_t __pad[4]; diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c index a658de9..4c1fe8c 100644 --- a/sys/rpc/clnt_dg.c +++ b/sys/rpc/clnt_dg.c @@ -682,6 +682,7 @@ get_reply: next_sendtime += retransmit_time; goto send_again; } + cu->cu_sent += CWNDSCALE; TAILQ_INSERT_TAIL(&cs->cs_pending, cr, cr_link); } @@ -733,6 +734,7 @@ got_reply: */ XDR_DESTROY(&xdrs); mtx_lock(&cs->cs_lock); + cu->cu_sent += CWNDSCALE; TAILQ_INSERT_TAIL(&cs->cs_pending, cr, cr_link); cr->cr_mrep = NULL; diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h index dd55875..559d571 100644 --- a/sys/security/audit/audit.h +++ b/sys/security/audit/audit.h @@ -114,7 +114,7 @@ void audit_arg_auditon(union auditon_udata *udata); void audit_arg_file(struct proc *p, struct file *fp); void audit_arg_argv(char *argv, int argc, int length); void audit_arg_envv(char *envv, int envc, int length); -void audit_arg_rights(cap_rights_t rights); +void audit_arg_rights(cap_rights_t *rightsp); void audit_arg_fcntl_rights(uint32_t fcntlrights); void audit_sysclose(struct thread *td, int fd); void audit_cred_copy(struct ucred *src, struct ucred *dest); diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index 4927be0..2e86842 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -861,7 +861,7 @@ audit_arg_envv(char *envv, int envc, int length) } void -audit_arg_rights(cap_rights_t rights) +audit_arg_rights(cap_rights_t *rightsp) { struct kaudit_record *ar; @@ -869,7 +869,7 @@ audit_arg_rights(cap_rights_t rights) if (ar == NULL) return; - ar->k_ar.ar_arg_rights = rights; + ar->k_ar.ar_arg_rights = *rightsp; ARG_SET_VALID(ar, ARG_RIGHTS); } diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c index 03b3c23..9f29ece 100644 --- a/sys/security/audit/audit_bsm.c +++ b/sys/security/audit/audit_bsm.c @@ -1611,14 +1611,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau) } break; - case AUE_CAP_NEW: case AUE_CAP_RIGHTS_LIMIT: /* * XXXRW/XXXJA: Would be nice to audit socket/etc information. */ FD_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_RIGHTS)) { - tok = au_to_arg64(2, "rights", ar->ar_arg_rights); + tok = au_to_rights(&ar->ar_arg_rights); kau_write(rec, tok); } break; diff --git a/sys/security/audit/audit_bsm_klib.c b/sys/security/audit/audit_bsm_klib.c index 5f5d58b..d06c770 100644 --- a/sys/security/audit/audit_bsm_klib.c +++ b/sys/security/audit/audit_bsm_klib.c @@ -496,7 +496,7 @@ audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath) vhold(cvnp); } else { /* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */ - error = fgetvp(td, dirfd, 0, &cvnp); + error = fgetvp(td, dirfd, NULL, &cvnp); if (error) { cpath[0] = '\0'; if (rvnp != NULL) diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h index e23ba08..b5c373a 100644 --- a/sys/security/audit/audit_private.h +++ b/sys/security/audit/audit_private.h @@ -41,6 +41,7 @@ #error "no user-serviceable parts inside" #endif +#include <sys/caprights.h> #include <sys/ipc.h> #include <sys/socket.h> #include <sys/ucred.h> diff --git a/sys/security/audit/bsm_token.c b/sys/security/audit/bsm_token.c index 6d0d67f..763d597 100644 --- a/sys/security/audit/bsm_token.c +++ b/sys/security/audit/bsm_token.c @@ -835,6 +835,22 @@ au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, tid)); } +token_t * +au_to_rights(cap_rights_t *rightsp) +{ + token_t *t; + u_char *dptr; + int i; + + GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(*rightsp)); + + ADD_U_CHAR(dptr, AUT_RIGHTS); + for (i = 0; i < nitems(rightsp->cr_rights); i++) + ADD_U_INT64(dptr, rightsp->cr_rights[i]); + + return (t); +} + /* * token ID 1 byte * error status 1 byte diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c index ff55ec9..6405586 100644 --- a/sys/security/mac/mac_syscalls.c +++ b/sys/security/mac/mac_syscalls.c @@ -229,6 +229,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) struct vnode *vp; struct pipe *pipe; struct socket *so; + cap_rights_t rights; short label_type; int error; @@ -248,7 +249,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = fget(td, uap->fd, CAP_MAC_GET, &fp); + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_MAC_GET), &fp); if (error) goto out; @@ -425,6 +426,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) struct mount *mp; struct vnode *vp; struct mac mac; + cap_rights_t rights; char *buffer; int error; @@ -443,7 +445,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); } - error = fget(td, uap->fd, CAP_MAC_SET, &fp); + error = fget(td, uap->fd, cap_rights_init(&rights, CAP_MAC_SET), &fp); if (error) goto out; diff --git a/sys/sys/_types.h b/sys/sys/_types.h index 34d1edb..ffef9d8 100644 --- a/sys/sys/_types.h +++ b/sys/sys/_types.h @@ -38,7 +38,6 @@ typedef __uint32_t __blksize_t; /* file block size */ typedef __int64_t __blkcnt_t; /* file block count */ typedef __int32_t __clockid_t; /* clock_gettime()... */ -typedef __uint64_t __cap_rights_t; /* capability rights */ typedef __uint32_t __fflags_t; /* file flags */ typedef __uint64_t __fsblkcnt_t; typedef __uint64_t __fsfilcnt_t; diff --git a/sys/sys/capability.h b/sys/sys/capability.h index ec63de7..e5b9ec7 100644 --- a/sys/sys/capability.h +++ b/sys/sys/capability.h @@ -42,9 +42,16 @@ #include <sys/cdefs.h> #include <sys/param.h> +#include <sys/caprights.h> #include <sys/file.h> #include <sys/fcntl.h> +#ifndef _KERNEL +#include <stdbool.h> +#endif + +#define CAPRIGHT(idx, bit) ((1ULL << (57 + (idx))) | (bit)) + /* * Possible rights on capabilities. * @@ -59,29 +66,31 @@ * involve reads or writes depending a great deal on context. */ -#define CAP_NONE 0x0000000000000000ULL +/* INDEX 0 */ /* * General file I/O. */ /* Allows for openat(O_RDONLY), read(2), readv(2). */ -#define CAP_READ 0x0000000000000001ULL +#define CAP_READ CAPRIGHT(0, 0x0000000000000001ULL) /* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */ -#define CAP_WRITE 0x0000000000000002ULL +#define CAP_WRITE CAPRIGHT(0, 0x0000000000000002ULL) +/* Allows for lseek(fd, 0, SEEK_CUR). */ +#define CAP_SEEK_TELL CAPRIGHT(0, 0x0000000000000004ULL) /* Allows for lseek(2). */ -#define CAP_SEEK 0x0000000000000080ULL +#define CAP_SEEK (CAP_SEEK_TELL | 0x0000000000000008ULL) /* Allows for pread(2), preadv(2). */ #define CAP_PREAD (CAP_SEEK | CAP_READ) /* Allows for openat(O_WRONLY) (without O_APPEND), pwrite(2), pwritev(2). */ #define CAP_PWRITE (CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_NONE). */ -#define CAP_MMAP 0x0000000000000004ULL +#define CAP_MMAP CAPRIGHT(0, 0x0000000000000010ULL) /* Allows for mmap(PROT_READ). */ #define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ) /* Allows for mmap(PROT_WRITE). */ #define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_EXEC). */ -#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL) +#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000020ULL) /* Allows for mmap(PROT_READ | PROT_WRITE). */ #define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W) /* Allows for mmap(PROT_READ | PROT_EXEC). */ @@ -91,67 +100,67 @@ /* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */ #define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X) /* Allows for openat(O_CREAT). */ -#define CAP_CREATE 0x0000000000080000ULL +#define CAP_CREATE CAPRIGHT(0, 0x0000000000000040ULL) /* Allows for openat(O_EXEC) and fexecve(2) in turn. */ -#define CAP_FEXECVE 0x0000000000000010ULL +#define CAP_FEXECVE CAPRIGHT(0, 0x0000000000000080ULL) /* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2). */ -#define CAP_FSYNC 0x0000000000000020ULL +#define CAP_FSYNC CAPRIGHT(0, 0x0000000000000100ULL) /* Allows for openat(O_TRUNC), ftruncate(2). */ -#define CAP_FTRUNCATE 0x0000000000000040ULL - -/* VFS methods. */ -#define CAP_FCHDIR 0x0000000000000200ULL -#define CAP_FCHFLAGS 0x0000000000000100ULL -#define CAP_CHFLAGSAT CAP_FCHFLAGS -#define CAP_FCHMOD 0x0000000000000400ULL -#define CAP_FCHMODAT CAP_FCHMOD -#define CAP_FCHOWN 0x0000000000000800ULL -#define CAP_FCHOWNAT CAP_FCHOWN -#define CAP_FCNTL 0x0000000000001000ULL -#define CAP_FLOCK 0x0000000000004000ULL -#define CAP_FPATHCONF 0x0000000000002000ULL -#define CAP_FSCK 0x0000000000008000ULL -#define CAP_FSTAT 0x0000000000010000ULL -#define CAP_FSTATAT CAP_FSTAT -#define CAP_FSTATFS 0x0000000000020000ULL -#define CAP_FUTIMES 0x0000000000040000ULL -#define CAP_FUTIMESAT CAP_FUTIMES -#define CAP_LINKAT 0x0000000000400000ULL -#define CAP_MKDIRAT 0x0000000000200000ULL -#define CAP_MKFIFOAT 0x0000000000800000ULL -#define CAP_MKNODAT 0x0080000000000000ULL -#define CAP_RENAMEAT 0x0200000000000000ULL -#define CAP_SYMLINKAT 0x0100000000000000ULL -#define CAP_UNLINKAT 0x0000000000100000ULL +#define CAP_FTRUNCATE CAPRIGHT(0, 0x0000000000000200ULL) /* Lookups - used to constrain *at() calls. */ -#define CAP_LOOKUP 0x0000000001000000ULL +#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL) + +/* VFS methods. */ +#define CAP_FCHDIR CAPRIGHT(0, 0x0000000000000800ULL) +#define CAP_FCHFLAGS CAPRIGHT(0, 0x0000000000001000ULL) +#define CAP_CHFLAGSAT (CAP_FCHFLAGS | CAP_LOOKUP) +#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL) +#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP) +#define CAP_FCHOWN CAPRIGHT(0, 0x0000000000004000ULL) +#define CAP_FCHOWNAT (CAP_FCHOWN | CAP_LOOKUP) +#define CAP_FCNTL CAPRIGHT(0, 0x0000000000008000ULL) +#define CAP_FLOCK CAPRIGHT(0, 0x0000000000010000ULL) +#define CAP_FPATHCONF CAPRIGHT(0, 0x0000000000020000ULL) +#define CAP_FSCK CAPRIGHT(0, 0x0000000000040000ULL) +#define CAP_FSTAT CAPRIGHT(0, 0x0000000000080000ULL) +#define CAP_FSTATAT (CAP_FSTAT | CAP_LOOKUP) +#define CAP_FSTATFS CAPRIGHT(0, 0x0000000000100000ULL) +#define CAP_FUTIMES CAPRIGHT(0, 0x0000000000200000ULL) +#define CAP_FUTIMESAT (CAP_FUTIMES | CAP_LOOKUP) +#define CAP_LINKAT CAPRIGHT(0, 0x0000000000400000ULL) +#define CAP_MKDIRAT CAPRIGHT(0, 0x0000000000800000ULL) +#define CAP_MKFIFOAT CAPRIGHT(0, 0x0000000001000000ULL) +#define CAP_MKNODAT CAPRIGHT(0, 0x0000000002000000ULL) +#define CAP_RENAMEAT CAPRIGHT(0, 0x0000000004000000ULL) +#define CAP_SYMLINKAT CAPRIGHT(0, 0x0000000008000000ULL) +#define CAP_UNLINKAT CAPRIGHT(0, 0x0000000010000000ULL) /* Extended attributes. */ -#define CAP_EXTATTR_DELETE 0x0000000002000000ULL -#define CAP_EXTATTR_GET 0x0000000004000000ULL -#define CAP_EXTATTR_LIST 0x0000000008000000ULL -#define CAP_EXTATTR_SET 0x0000000010000000ULL +#define CAP_EXTATTR_DELETE CAPRIGHT(0, 0x0000000020000000ULL) +#define CAP_EXTATTR_GET CAPRIGHT(0, 0x0000000040000000ULL) +#define CAP_EXTATTR_LIST CAPRIGHT(0, 0x0000000080000000ULL) +#define CAP_EXTATTR_SET CAPRIGHT(0, 0x0000000100000000ULL) /* Access Control Lists. */ -#define CAP_ACL_CHECK 0x0000000020000000ULL -#define CAP_ACL_DELETE 0x0000000040000000ULL -#define CAP_ACL_GET 0x0000000080000000ULL -#define CAP_ACL_SET 0x0000000100000000ULL +#define CAP_ACL_CHECK CAPRIGHT(0, 0x0000000200000000ULL) +#define CAP_ACL_DELETE CAPRIGHT(0, 0x0000000400000000ULL) +#define CAP_ACL_GET CAPRIGHT(0, 0x0000000800000000ULL) +#define CAP_ACL_SET CAPRIGHT(0, 0x0000001000000000ULL) /* Socket operations. */ -#define CAP_ACCEPT 0x0000000200000000ULL -#define CAP_BIND 0x0000000400000000ULL -#define CAP_CONNECT 0x0000000800000000ULL -#define CAP_GETPEERNAME 0x0000001000000000ULL -#define CAP_GETSOCKNAME 0x0000002000000000ULL -#define CAP_GETSOCKOPT 0x0000004000000000ULL -#define CAP_LISTEN 0x0000008000000000ULL -#define CAP_PEELOFF 0x0000010000000000ULL +#define CAP_ACCEPT CAPRIGHT(0, 0x0000002000000000ULL) +#define CAP_BIND CAPRIGHT(0, 0x0000004000000000ULL) +#define CAP_CONNECT CAPRIGHT(0, 0x0000008000000000ULL) +#define CAP_GETPEERNAME CAPRIGHT(0, 0x0000010000000000ULL) +#define CAP_GETSOCKNAME CAPRIGHT(0, 0x0000020000000000ULL) +#define CAP_GETSOCKOPT CAPRIGHT(0, 0x0000040000000000ULL) +#define CAP_LISTEN CAPRIGHT(0, 0x0000080000000000ULL) +#define CAP_PEELOFF CAPRIGHT(0, 0x0000100000000000ULL) #define CAP_RECV CAP_READ #define CAP_SEND CAP_WRITE -#define CAP_SETSOCKOPT 0x0000020000000000ULL -#define CAP_SHUTDOWN 0x0000040000000000ULL +#define CAP_SETSOCKOPT CAPRIGHT(0, 0x0000200000000000ULL) +#define CAP_SHUTDOWN CAPRIGHT(0, 0x0000400000000000ULL) #define CAP_SOCK_CLIENT \ (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \ @@ -161,56 +170,69 @@ CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \ CAP_SETSOCKOPT | CAP_SHUTDOWN) +/* All used bits for index 0. */ +#define CAP_ALL0 CAPRIGHT(0, 0x00007FFFFFFFFFFFULL) + +/* Available bits for index 0. */ +#define CAP_UNUSED0_48 CAPRIGHT(0, 0x0000800000000000ULL) +/* ... */ +#define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL) + +/* INDEX 1 */ + /* Mandatory Access Control. */ -#define CAP_MAC_GET 0x0000080000000000ULL -#define CAP_MAC_SET 0x0000100000000000ULL +#define CAP_MAC_GET CAPRIGHT(1, 0x0000000000000001ULL) +#define CAP_MAC_SET CAPRIGHT(1, 0x0000000000000002ULL) /* Methods on semaphores. */ -#define CAP_SEM_GETVALUE 0x0000200000000000ULL -#define CAP_SEM_POST 0x0000400000000000ULL -#define CAP_SEM_WAIT 0x0000800000000000ULL +#define CAP_SEM_GETVALUE CAPRIGHT(1, 0x0000000000000004ULL) +#define CAP_SEM_POST CAPRIGHT(1, 0x0000000000000008ULL) +#define CAP_SEM_WAIT CAPRIGHT(1, 0x0000000000000010ULL) /* kqueue events. */ -#define CAP_POLL_EVENT 0x0001000000000000ULL -#define CAP_POST_EVENT 0x0002000000000000ULL +#define CAP_POLL_EVENT CAPRIGHT(1, 0x0000000000000020ULL) +#define CAP_POST_EVENT CAPRIGHT(1, 0x0000000000000040ULL) /* Strange and powerful rights that should not be given lightly. */ -#define CAP_IOCTL 0x0004000000000000ULL -#define CAP_TTYHOOK 0x0008000000000000ULL +#define CAP_IOCTL CAPRIGHT(1, 0x0000000000000080ULL) +#define CAP_TTYHOOK CAPRIGHT(1, 0x0000000000000100ULL) /* Process management via process descriptors. */ -#define CAP_PDGETPID 0x0010000000000000ULL -#define CAP_PDWAIT 0x0020000000000000ULL -#define CAP_PDKILL 0x0040000000000000ULL +#define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL) +#define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL) +#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) /* * Rights that allow to use bindat(2) and connectat(2) syscalls on a * directory descriptor. */ -#define CAP_BINDAT 0x0400000000000000ULL -#define CAP_CONNECTAT 0x0800000000000000ULL - -/* The mask of all valid method rights. */ -#define CAP_MASK_VALID 0x0fffffffffffffffULL -#define CAP_ALL CAP_MASK_VALID - -/* Available bits. */ -#define CAP_UNUSED3 0x1000000000000000ULL -#define CAP_UNUSED2 0x2000000000000000ULL -#define CAP_UNUSED1 0x4000000000000000ULL -#define CAP_UNUSED0 0x8000000000000000ULL - -/* - * The following defines are provided for backward API compatibility and - * should not be used in new code. - */ -#define CAP_MAPEXEC CAP_MMAP_X -#define CAP_DELETE CAP_UNLINKAT -#define CAP_MKDIR CAP_MKDIRAT -#define CAP_RMDIR CAP_UNLINKAT -#define CAP_MKFIFO CAP_MKFIFOAT -#define CAP_MKNOD CAP_MKNODAT -#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER) +#define CAP_BINDAT CAPRIGHT(1, 0x0000000000001000ULL) +#define CAP_CONNECTAT CAPRIGHT(1, 0x0000000000002000ULL) + +/* All used bits for index 1. */ +#define CAP_ALL1 CAPRIGHT(1, 0x0000000000003FFFULL) + +/* Available bits for index 1. */ +#define CAP_UNUSED1_15 CAPRIGHT(1, 0x0000000000004000ULL) +/* ... */ +#define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL) + +#define CAP_ALL(rights) do { \ + (rights)->cr_rights[0] = \ + ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAP_ALL0; \ + (rights)->cr_rights[1] = CAP_ALL1; \ +} while (0) + +#define CAP_NONE(rights) do { \ + (rights)->cr_rights[0] = \ + ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAPRIGHT(0, 0ULL); \ + (rights)->cr_rights[1] = CAPRIGHT(1, 0ULL); \ +} while (0) + +#define CAPRVER(right) ((int)((right) >> 62)) +#define CAPVER(rights) CAPRVER((rights)->cr_rights[0]) +#define CAPARSIZE(rights) (CAPVER(rights) + 2) +#define CAPIDXBIT(right) ((int)(((right) >> 57) & 0x1F)) /* * Allowed fcntl(2) commands. @@ -230,6 +252,27 @@ #define CAP_IOCTLS_ALL SSIZE_MAX +#define cap_rights_init(...) \ + __cap_rights_init(CAP_RIGHTS_VERSION, __VA_ARGS__, 0ULL) +cap_rights_t *__cap_rights_init(int version, cap_rights_t *rights, ...); + +#define cap_rights_set(rights, ...) \ + __cap_rights_set((rights), __VA_ARGS__, 0ULL) +void __cap_rights_set(cap_rights_t *rights, ...); + +#define cap_rights_clear(rights, ...) \ + __cap_rights_clear((rights), __VA_ARGS__, 0ULL) +void __cap_rights_clear(cap_rights_t *rights, ...); + +#define cap_rights_is_set(rights, ...) \ + __cap_rights_is_set((rights), __VA_ARGS__, 0ULL) +bool __cap_rights_is_set(const cap_rights_t *rights, ...); + +bool cap_rights_is_valid(const cap_rights_t *rights); +void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); +void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); +bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); + #ifdef _KERNEL #include <sys/systm.h> @@ -241,17 +284,17 @@ struct filedesc; /* * Test whether a capability grants the requested rights. */ -int cap_check(cap_rights_t have, cap_rights_t need); +int cap_check(const cap_rights_t *havep, const cap_rights_t *needp); /* * Convert capability rights into VM access flags. */ -u_char cap_rights_to_vmprot(cap_rights_t have); +u_char cap_rights_to_vmprot(cap_rights_t *havep); /* * For the purposes of procstat(1) and similar tools, allow kern_descrip.c to * extract the rights from a capability. */ -cap_rights_t cap_rights(struct filedesc *fdp, int fd); +cap_rights_t *cap_rights(struct filedesc *fdp, int fd); int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd); int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); @@ -259,18 +302,11 @@ int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); #else /* !_KERNEL */ __BEGIN_DECLS -#include <stdbool.h> - /* * cap_enter(): Cause the process to enter capability mode, which will * prevent it from directly accessing global namespaces. System calls will * be limited to process-local, process-inherited, or file descriptor * operations. If already in capability mode, a no-op. - * - * Currently, process-inherited operations are not properly handled -- in - * particular, we're interested in things like waitpid(2), kill(2), etc, - * being properly constrained. One possible solution is to introduce process - * descriptors. */ int cap_enter(void); @@ -288,11 +324,12 @@ int cap_getmode(u_int *modep); /* * Limits capability rights for the given descriptor (CAP_*). */ -int cap_rights_limit(int fd, cap_rights_t rights); +int cap_rights_limit(int fd, const cap_rights_t *rights); /* - * Returns bitmask of capability rights for the given descriptor. + * Returns capability rights for the given descriptor. */ -int cap_rights_get(int fd, cap_rights_t *rightsp); +#define cap_rights_get(fd, rights) __cap_rights_get(CAP_RIGHTS_VERSION, (fd), (rights)) +int __cap_rights_get(int version, int fd, cap_rights_t *rightsp); /* * Limits allowed ioctls for the given descriptor. */ @@ -312,10 +349,6 @@ int cap_fcntls_limit(int fd, uint32_t fcntlrights); */ int cap_fcntls_get(int fd, uint32_t *fcntlrightsp); -/* For backward compatibility. */ -int cap_new(int fd, cap_rights_t rights); -#define cap_getrights(fd, rightsp) cap_rights_get((fd), (rightsp)) - __END_DECLS #endif /* !_KERNEL */ diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h new file mode 100644 index 0000000..eb8e454 --- /dev/null +++ b/sys/sys/caprights.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2013 FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_CAPRIGHTS_H_ +#define _SYS_CAPRIGHTS_H_ + +/* + * The top two bits in the first element of the cr_rights[] array contain + * total number of elements in the array - 2. This means if those two bits are + * equal to 0, we have 2 array elements. + * The top two bits in all remaining array elements should be 0. + * The next five bits contain array index. Only one bit is used and bit position + * in this five-bits range defines array index. This means there can be at most + * five array elements. + */ +#define CAP_RIGHTS_VERSION_00 0 +/* +#define CAP_RIGHTS_VERSION_01 1 +#define CAP_RIGHTS_VERSION_02 2 +#define CAP_RIGHTS_VERSION_03 3 +*/ +#define CAP_RIGHTS_VERSION CAP_RIGHTS_VERSION_00 + +struct cap_rights { + uint64_t cr_rights[CAP_RIGHTS_VERSION + 2]; +}; + +#ifndef _CAP_RIGHTS_T_DECLARED +#define _CAP_RIGHTS_T_DECLARED +typedef struct cap_rights cap_rights_t; +#endif + +#endif /* !_SYS_CAPRIGHTS_H_ */ diff --git a/sys/sys/file.h b/sys/sys/file.h index 72c512f..7b373f0 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -217,12 +217,12 @@ extern int maxfiles; /* kernel limit on number of open files */ extern int maxfilesperproc; /* per process limit on number of open files */ extern volatile int openfiles; /* actual number of open files */ -int fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp); -int fget_mmap(struct thread *td, int fd, cap_rights_t rights, +int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); +int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, u_char *maxprotp, struct file **fpp); -int fget_read(struct thread *td, int fd, cap_rights_t rights, +int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); -int fget_write(struct thread *td, int fd, cap_rights_t rights, +int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); int _fdrop(struct file *fp, struct thread *td); @@ -248,17 +248,18 @@ fo_sendfile_t vn_sendfile; fo_seek_t vn_seek; void finit(struct file *, u_int, short, void *, struct fileops *); -int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp); -int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, +int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_rights(struct thread *td, int fd, cap_rights_t need, +int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, + struct vnode **vpp); +int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, struct filecaps *havecaps, struct vnode **vpp); -int fgetvp_read(struct thread *td, int fd, cap_rights_t rights, +int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_write(struct thread *td, int fd, cap_rights_t rights, +int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp); -int fgetsock(struct thread *td, int fd, cap_rights_t rights, +int fgetsock(struct thread *td, int fd, cap_rights_t *rightsp, struct socket **spp, u_int *fflagp); void fputsock(struct socket *sp); diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 9f73915..968ceff 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -33,6 +33,7 @@ #ifndef _SYS_FILEDESC_H_ #define _SYS_FILEDESC_H_ +#include <sys/caprights.h> #include <sys/queue.h> #include <sys/event.h> #include <sys/lock.h> @@ -108,10 +109,6 @@ struct filedesc_to_leader { #ifdef _KERNEL -#include <sys/systm.h> /* CTASSERT() */ - -CTASSERT(sizeof(cap_rights_t) == sizeof(uint64_t)); - /* Flags for do_dup() */ #define DUP_FIXED 0x1 /* Force fixed allocation. */ #define DUP_FCNTL 0x2 /* fcntl()-style errors. */ @@ -163,13 +160,13 @@ struct filedesc *fdshare(struct filedesc *fdp); struct filedesc_to_leader * filedesc_to_leader_alloc(struct filedesc_to_leader *old, struct filedesc *fdp, struct proc *leader); -int getvnode(struct filedesc *fdp, int fd, cap_rights_t rights, +int getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp); void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); void setugidsafety(struct thread *td); /* Return a referenced file from an unlocked descriptor. */ -int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights, +int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, int needfcntl, struct file **fpp, cap_rights_t *haverightsp); /* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */ diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index b3e6be8..e9cfa6e 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -33,6 +33,8 @@ #ifndef _SYS_KTRACE_H_ #define _SYS_KTRACE_H_ +#include <sys/caprights.h> + /* * operations to ktrace system call (KTROP(op)) */ @@ -264,7 +266,10 @@ void ktrprocexit(struct thread *); void ktrprocfork(struct proc *, struct proc *); void ktruserret(struct thread *); void ktrstruct(const char *, void *, size_t); -void ktrcapfail(enum ktr_cap_fail_type, cap_rights_t, cap_rights_t); +void ktrcapfail(enum ktr_cap_fail_type, const cap_rights_t *, + const cap_rights_t *); +#define ktrcaprights(s) \ + ktrstruct("caprights", (s), sizeof(cap_rights_t)) #define ktrsockaddr(s) \ ktrstruct("sockaddr", (s), ((struct sockaddr *)(s))->sa_len) #define ktrstat(s) \ diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 1a835b7..8f94451 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -609,6 +609,7 @@ typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op, struct sysctl_req *req); typedef void vfs_susp_clean_t(struct mount *mp); typedef void vfs_notify_lowervp_t(struct mount *mp, struct vnode *lowervp); +typedef void vfs_purge_t(struct mount *mp); struct vfsops { vfs_mount_t *vfs_mount; @@ -628,6 +629,7 @@ struct vfsops { vfs_susp_clean_t *vfs_susp_clean; vfs_notify_lowervp_t *vfs_reclaim_lowervp; vfs_notify_lowervp_t *vfs_unlink_lowervp; + vfs_purge_t *vfs_purge; vfs_mount_t *vfs_spare[6]; /* spares for ABI compat */ }; @@ -757,6 +759,14 @@ vfs_statfs_t __vfs_statfs; } \ } while (0) +#define VFS_PURGE(MP) do { \ + if (*(MP)->mnt_op->vfs_purge != NULL) { \ + VFS_PROLOGUE(MP); \ + (*(MP)->mnt_op->vfs_purge)(MP); \ + VFS_EPILOGUE(MP); \ + } \ +} while (0) + #define VFS_KNOTE_LOCKED(vp, hint) do \ { \ if (((vp)->v_vflag & VV_NOKNOTE) == 0) \ diff --git a/sys/sys/mouse.h b/sys/sys/mouse.h index e0b70ff..e03bc40 100644 --- a/sys/sys/mouse.h +++ b/sys/sys/mouse.h @@ -107,6 +107,9 @@ typedef struct synapticshw { int capMultiFinger; int capPalmDetect; int capPassthrough; + int capMiddle; + int nExtendedButtons; + int nExtendedQueries; } synapticshw_t; /* iftype */ diff --git a/sys/sys/namei.h b/sys/sys/namei.h index a9992f4..f1b1223 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -33,6 +33,7 @@ #ifndef _SYS_NAMEI_H_ #define _SYS_NAMEI_H_ +#include <sys/caprights.h> #include <sys/filedesc.h> #include <sys/queue.h> #include <sys/uio.h> @@ -158,32 +159,14 @@ struct nameidata { NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, 0, td) #define NDINIT_AT(ndp, op, flags, segflg, namep, dirfd, td) \ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, 0, td) -#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rights, td) \ - NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rights, td) +#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rightsp, td) \ + NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rightsp, td) #define NDINIT_ATVP(ndp, op, flags, segflg, namep, vp, td) \ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, 0, td) -static __inline void -NDINIT_ALL(struct nameidata *ndp, - u_long op, u_long flags, - enum uio_seg segflg, - const char *namep, - int dirfd, - struct vnode *startdir, - cap_rights_t rights, - struct thread *td) -{ - ndp->ni_cnd.cn_nameiop = op; - ndp->ni_cnd.cn_flags = flags; - ndp->ni_segflg = segflg; - ndp->ni_dirp = namep; - ndp->ni_dirfd = dirfd; - ndp->ni_startdir = startdir; - ndp->ni_strictrelative = 0; - ndp->ni_rightsneeded = rights; - filecaps_init(&ndp->ni_filecaps); - ndp->ni_cnd.cn_thread = td; -} +void NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, + enum uio_seg segflg, const char *namep, int dirfd, struct vnode *startdir, + cap_rights_t *rightsp, struct thread *td); #define NDF_NO_DVP_RELE 0x00000001 #define NDF_NO_DVP_UNLOCK 0x00000002 diff --git a/sys/sys/param.h b/sys/sys/param.h index 2ba9201..fa3e2eb 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000051 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000053 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h index cc8b716..4d77a05 100644 --- a/sys/sys/procdesc.h +++ b/sys/sys/procdesc.h @@ -92,8 +92,8 @@ struct procdesc { * In-kernel interfaces to process descriptors. */ int procdesc_exit(struct proc *); -int procdesc_find(struct thread *, int fd, cap_rights_t, struct proc **); -int kern_pdgetpid(struct thread *, int fd, cap_rights_t, pid_t *pidp); +int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **); +int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp); void procdesc_new(struct proc *, int); void procdesc_finit(struct procdesc *, struct file *); pid_t procdesc_pid(struct file *); diff --git a/sys/sys/sf_buf.h b/sys/sys/sf_buf.h index 4c37e00..61643b0 100644 --- a/sys/sys/sf_buf.h +++ b/sys/sys/sf_buf.h @@ -54,6 +54,7 @@ struct sfstat { /* sendfile statistics */ #ifdef _KERNEL #include <machine/sf_buf.h> +#include <sys/systm.h> #include <sys/counter.h> struct mbuf; /* for sf_buf_mext() */ diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h index bfccd74..402a8f0 100644 --- a/sys/sys/sockbuf.h +++ b/sys/sys/sockbuf.h @@ -97,7 +97,7 @@ struct sockbuf { u_int sb_mbmax; /* (c/d) max chars of mbufs to use */ u_int sb_ctl; /* (c/d) non-data chars in buffer */ int sb_lowat; /* (c/d) low water mark */ - int sb_timeo; /* (c/d) timeout for read/write */ + sbintime_t sb_timeo; /* (c/d) timeout for read/write */ short sb_flags; /* (c/d) flags, see below */ int (*sb_upcall)(struct socket *, void *, int); /* (c/d) */ void *sb_upcallarg; /* (c/d) */ diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index b321416..ad3c73a 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 251526 2013-06-08 13:27:57Z glebius + * created from FreeBSD: head/sys/kern/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #define SYS_syscall 0 @@ -434,8 +434,8 @@ #define SYS_msgctl 511 #define SYS_shmctl 512 #define SYS_lpathconf 513 -#define SYS_cap_new 514 -#define SYS_cap_rights_get 515 + /* 514 is obsolete cap_new */ +#define SYS___cap_rights_get 515 #define SYS_cap_enter 516 #define SYS_cap_getmode 517 #define SYS_pdfork 518 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index df7d19f..eaf7378 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,7 +1,7 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. # $FreeBSD$ -# created from FreeBSD: head/sys/kern/syscalls.master 251526 2013-06-08 13:27:57Z glebius +# created from FreeBSD: head/sys/kern/syscalls.master 255219 2013-09-05 00:09:56Z pjd MIASM = \ syscall.o \ exit.o \ @@ -383,8 +383,7 @@ MIASM = \ msgctl.o \ shmctl.o \ lpathconf.o \ - cap_new.o \ - cap_rights_get.o \ + __cap_rights_get.o \ cap_enter.o \ cap_getmode.o \ pdfork.o \ diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 6a54152..5f8a217 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 251526 2013-06-08 13:27:57Z glebius + * created from FreeBSD: head/sys/kern/syscalls.master 255219 2013-09-05 00:09:56Z pjd */ #ifndef _SYS_SYSPROTO_H_ @@ -1672,13 +1672,10 @@ struct lpathconf_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; -struct cap_new_args { +struct __cap_rights_get_args { + char version_l_[PADL_(int)]; int version; char version_r_[PADR_(int)]; char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char rights_l_[PADL_(uint64_t)]; uint64_t rights; char rights_r_[PADR_(uint64_t)]; -}; -struct cap_rights_get_args { - char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char rightsp_l_[PADL_(uint64_t *)]; uint64_t * rightsp; char rightsp_r_[PADR_(uint64_t *)]; + char rightsp_l_[PADL_(cap_rights_t *)]; cap_rights_t * rightsp; char rightsp_r_[PADR_(cap_rights_t *)]; }; struct cap_enter_args { register_t dummy; @@ -1764,7 +1761,7 @@ struct wait6_args { }; struct cap_rights_limit_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char rights_l_[PADL_(uint64_t)]; uint64_t rights; char rights_r_[PADR_(uint64_t)]; + char rightsp_l_[PADL_(cap_rights_t *)]; cap_rights_t * rightsp; char rightsp_r_[PADR_(cap_rights_t *)]; }; struct cap_ioctls_limit_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; @@ -2179,8 +2176,7 @@ int sys___semctl(struct thread *, struct __semctl_args *); int sys_msgctl(struct thread *, struct msgctl_args *); int sys_shmctl(struct thread *, struct shmctl_args *); int sys_lpathconf(struct thread *, struct lpathconf_args *); -int sys_cap_new(struct thread *, struct cap_new_args *); -int sys_cap_rights_get(struct thread *, struct cap_rights_get_args *); +int sys___cap_rights_get(struct thread *, struct __cap_rights_get_args *); int sys_cap_enter(struct thread *, struct cap_enter_args *); int sys_cap_getmode(struct thread *, struct cap_getmode_args *); int sys_pdfork(struct thread *, struct pdfork_args *); @@ -2886,8 +2882,7 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *); #define SYS_AUE_msgctl AUE_MSGCTL #define SYS_AUE_shmctl AUE_SHMCTL #define SYS_AUE_lpathconf AUE_LPATHCONF -#define SYS_AUE_cap_new AUE_CAP_NEW -#define SYS_AUE_cap_rights_get AUE_CAP_RIGHTS_GET +#define SYS_AUE___cap_rights_get AUE_CAP_RIGHTS_GET #define SYS_AUE_cap_enter AUE_CAP_ENTER #define SYS_AUE_cap_getmode AUE_CAP_GETMODE #define SYS_AUE_pdfork AUE_PDFORK diff --git a/sys/sys/time.h b/sys/sys/time.h index d260cc7..82a7db1 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -56,64 +56,64 @@ struct bintime { }; static __inline void -bintime_addx(struct bintime *bt, uint64_t x) +bintime_addx(struct bintime *_bt, uint64_t _x) { - uint64_t u; + uint64_t _u; - u = bt->frac; - bt->frac += x; - if (u > bt->frac) - bt->sec++; + _u = _bt->frac; + _bt->frac += _x; + if (_u > _bt->frac) + _bt->sec++; } static __inline void -bintime_add(struct bintime *bt, const struct bintime *bt2) +bintime_add(struct bintime *_bt, const struct bintime *_bt2) { - uint64_t u; + uint64_t _u; - u = bt->frac; - bt->frac += bt2->frac; - if (u > bt->frac) - bt->sec++; - bt->sec += bt2->sec; + _u = _bt->frac; + _bt->frac += _bt2->frac; + if (_u > _bt->frac) + _bt->sec++; + _bt->sec += _bt2->sec; } static __inline void -bintime_sub(struct bintime *bt, const struct bintime *bt2) +bintime_sub(struct bintime *_bt, const struct bintime *_bt2) { - uint64_t u; + uint64_t _u; - u = bt->frac; - bt->frac -= bt2->frac; - if (u < bt->frac) - bt->sec--; - bt->sec -= bt2->sec; + _u = _bt->frac; + _bt->frac -= _bt2->frac; + if (_u < _bt->frac) + _bt->sec--; + _bt->sec -= _bt2->sec; } static __inline void -bintime_mul(struct bintime *bt, u_int x) +bintime_mul(struct bintime *_bt, u_int _x) { - uint64_t p1, p2; + uint64_t _p1, _p2; - p1 = (bt->frac & 0xffffffffull) * x; - p2 = (bt->frac >> 32) * x + (p1 >> 32); - bt->sec *= x; - bt->sec += (p2 >> 32); - bt->frac = (p2 << 32) | (p1 & 0xffffffffull); + _p1 = (_bt->frac & 0xffffffffull) * _x; + _p2 = (_bt->frac >> 32) * _x + (_p1 >> 32); + _bt->sec *= _x; + _bt->sec += (_p2 >> 32); + _bt->frac = (_p2 << 32) | (_p1 & 0xffffffffull); } static __inline void -bintime_shift(struct bintime *__bt, int __exp) +bintime_shift(struct bintime *_bt, int _exp) { - if (__exp > 0) { - __bt->sec <<= __exp; - __bt->sec |= __bt->frac >> (64 - __exp); - __bt->frac <<= __exp; - } else if (__exp < 0) { - __bt->frac >>= -__exp; - __bt->frac |= (uint64_t)__bt->sec << (64 + __exp); - __bt->sec >>= -__exp; + if (_exp > 0) { + _bt->sec <<= _exp; + _bt->sec |= _bt->frac >> (64 - _exp); + _bt->frac <<= _exp; + } else if (_exp < 0) { + _bt->frac >>= -_exp; + _bt->frac |= (uint64_t)_bt->sec << (64 + _exp); + _bt->sec >>= -_exp; } } @@ -131,27 +131,27 @@ bintime_shift(struct bintime *__bt, int __exp) #define SBT_1NS (SBT_1S / 1000000000) static __inline int -sbintime_getsec(sbintime_t sbt) +sbintime_getsec(sbintime_t _sbt) { - return (sbt >> 32); + return (_sbt >> 32); } static __inline sbintime_t -bttosbt(const struct bintime bt) +bttosbt(const struct bintime _bt) { - return (((sbintime_t)bt.sec << 32) + (bt.frac >> 32)); + return (((sbintime_t)_bt.sec << 32) + (_bt.frac >> 32)); } static __inline struct bintime -sbttobt(sbintime_t sbt) +sbttobt(sbintime_t _sbt) { - struct bintime bt; + struct bintime _bt; - bt.sec = sbt >> 32; - bt.frac = sbt << 32; - return (bt); + _bt.sec = _sbt >> 32; + _bt.frac = _sbt << 32; + return (_bt); } /*- @@ -169,73 +169,74 @@ sbttobt(sbintime_t sbt) */ static __inline void -bintime2timespec(const struct bintime *bt, struct timespec *ts) +bintime2timespec(const struct bintime *_bt, struct timespec *_ts) { - ts->tv_sec = bt->sec; - ts->tv_nsec = ((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32; + _ts->tv_sec = _bt->sec; + _ts->tv_nsec = ((uint64_t)1000000000 * + (uint32_t)(_bt->frac >> 32)) >> 32; } static __inline void -timespec2bintime(const struct timespec *ts, struct bintime *bt) +timespec2bintime(const struct timespec *_ts, struct bintime *_bt) { - bt->sec = ts->tv_sec; + _bt->sec = _ts->tv_sec; /* 18446744073 = int(2^64 / 1000000000) */ - bt->frac = ts->tv_nsec * (uint64_t)18446744073LL; + _bt->frac = _ts->tv_nsec * (uint64_t)18446744073LL; } static __inline void -bintime2timeval(const struct bintime *bt, struct timeval *tv) +bintime2timeval(const struct bintime *_bt, struct timeval *_tv) { - tv->tv_sec = bt->sec; - tv->tv_usec = ((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32; + _tv->tv_sec = _bt->sec; + _tv->tv_usec = ((uint64_t)1000000 * (uint32_t)(_bt->frac >> 32)) >> 32; } static __inline void -timeval2bintime(const struct timeval *tv, struct bintime *bt) +timeval2bintime(const struct timeval *_tv, struct bintime *_bt) { - bt->sec = tv->tv_sec; + _bt->sec = _tv->tv_sec; /* 18446744073709 = int(2^64 / 1000000) */ - bt->frac = tv->tv_usec * (uint64_t)18446744073709LL; + _bt->frac = _tv->tv_usec * (uint64_t)18446744073709LL; } static __inline struct timespec -sbttots(sbintime_t sbt) +sbttots(sbintime_t _sbt) { - struct timespec ts; + struct timespec _ts; - ts.tv_sec = sbt >> 32; - ts.tv_nsec = ((uint64_t)1000000000 * (uint32_t)sbt) >> 32; - return (ts); + _ts.tv_sec = _sbt >> 32; + _ts.tv_nsec = ((uint64_t)1000000000 * (uint32_t)_sbt) >> 32; + return (_ts); } static __inline sbintime_t -tstosbt(struct timespec ts) +tstosbt(struct timespec _ts) { - return (((sbintime_t)ts.tv_sec << 32) + - (ts.tv_nsec * (((uint64_t)1 << 63) / 500000000) >> 32)); + return (((sbintime_t)_ts.tv_sec << 32) + + (_ts.tv_nsec * (((uint64_t)1 << 63) / 500000000) >> 32)); } static __inline struct timeval -sbttotv(sbintime_t sbt) +sbttotv(sbintime_t _sbt) { - struct timeval tv; + struct timeval _tv; - tv.tv_sec = sbt >> 32; - tv.tv_usec = ((uint64_t)1000000 * (uint32_t)sbt) >> 32; - return (tv); + _tv.tv_sec = _sbt >> 32; + _tv.tv_usec = ((uint64_t)1000000 * (uint32_t)_sbt) >> 32; + return (_tv); } static __inline sbintime_t -tvtosbt(struct timeval tv) +tvtosbt(struct timeval _tv) { - return (((sbintime_t)tv.tv_sec << 32) + - (tv.tv_usec * (((uint64_t)1 << 63) / 500000) >> 32)); + return (((sbintime_t)_tv.tv_sec << 32) + + (_tv.tv_usec * (((uint64_t)1 << 63) / 500000) >> 32)); } #endif /* __BSD_VISIBLE */ @@ -411,10 +412,10 @@ void microuptime(struct timeval *tvp); static __inline sbintime_t sbinuptime(void) { - struct bintime bt; + struct bintime _bt; - binuptime(&bt); - return (bttosbt(bt)); + binuptime(&_bt); + return (bttosbt(_bt)); } void bintime(struct bintime *bt); @@ -428,10 +429,10 @@ void getmicrouptime(struct timeval *tvp); static __inline sbintime_t getsbinuptime(void) { - struct bintime bt; + struct bintime _bt; - getbinuptime(&bt); - return (bttosbt(bt)); + getbinuptime(&_bt); + return (bttosbt(_bt)); } void getbintime(struct bintime *bt); diff --git a/sys/sys/types.h b/sys/sys/types.h index cc0bca8..03eaa60 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -88,8 +88,6 @@ typedef __blkcnt_t blkcnt_t; #define _BLKCNT_T_DECLARED #endif -typedef __cap_rights_t cap_rights_t; - #ifndef _CLOCK_T_DECLARED typedef __clock_t clock_t; #define _CLOCK_T_DECLARED @@ -234,6 +232,13 @@ typedef __useconds_t useconds_t; /* microseconds (unsigned) */ #define _USECONDS_T_DECLARED #endif +#ifndef _CAP_RIGHTS_T_DECLARED +#define _CAP_RIGHTS_T_DECLARED +struct cap_rights; + +typedef struct cap_rights cap_rights_t; +#endif + typedef __vm_offset_t vm_offset_t; typedef __vm_ooffset_t vm_ooffset_t; typedef __vm_paddr_t vm_paddr_t; diff --git a/sys/sys/user.h b/sys/sys/user.h index 9389e55..349003d 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -61,6 +61,7 @@ #ifndef _SYS_SOCKET_VAR_H_ #include <sys/socket.h> #endif +#include <sys/caprights.h> /* * KERN_PROC subtype ops return arrays of selected proc structure entries: @@ -318,7 +319,7 @@ struct kinfo_ofile { }; #if defined(__amd64__) || defined(__i386__) -#define KINFO_FILE_SIZE 1392 +#define KINFO_FILE_SIZE 1424 #endif struct kinfo_file { @@ -389,6 +390,7 @@ struct kinfo_file { uint16_t kf_pad1; /* Round to 32 bit alignment. */ int _kf_ispare0; /* Space for more stuff. */ cap_rights_t kf_cap_rights; /* Capability rights. */ + uint64_t _kf_cap_spare[3]; /* Space for future cap_rights_t. */ int _kf_ispare[4]; /* Space for more stuff. */ /* Truncated before copyout in sysctl */ char kf_path[PATH_MAX]; /* Path to file, if any. */ diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 3063ade..19e880c 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -2709,6 +2709,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) long blkcnt, blksize; struct filedesc *fdp; struct file *fp, *vfp; + cap_rights_t rights; int filetype, error; static struct fileops *origops, bufferedops; @@ -2718,8 +2719,8 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) return (error); if (cmd.version != FFS_CMD_VERSION) return (ERPCMISMATCH); - if ((error = getvnode(td->td_proc->p_fd, cmd.handle, CAP_FSCK, - &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, cmd.handle, + cap_rights_init(&rights, CAP_FSCK), &fp)) != 0) return (error); vp = fp->f_data; if (vp->v_type != VREG && vp->v_type != VDIR) { @@ -3033,7 +3034,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) } #endif /* DEBUG */ if ((error = getvnode(td->td_proc->p_fd, cmd.value, - CAP_FSCK, &vfp)) != 0) + cap_rights_init(&rights, CAP_FSCK), &vfp)) != 0) break; if (vfp->f_vnode->v_type != VCHR) { fdrop(vfp, td); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 53a7be5..77f64f4 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -311,17 +311,17 @@ sys_mmap(td, uap) * rights, but also return the maximum rights to be combined * with maxprot later. */ - rights = CAP_MMAP; + cap_rights_init(&rights, CAP_MMAP); if (prot & PROT_READ) - rights |= CAP_MMAP_R; + cap_rights_set(&rights, CAP_MMAP_R); if ((flags & MAP_SHARED) != 0) { if (prot & PROT_WRITE) - rights |= CAP_MMAP_W; + cap_rights_set(&rights, CAP_MMAP_W); } if (prot & PROT_EXEC) - rights |= CAP_MMAP_X; - if ((error = fget_mmap(td, uap->fd, rights, &cap_maxprot, - &fp)) != 0) + cap_rights_set(&rights, CAP_MMAP_X); + error = fget_mmap(td, uap->fd, &rights, &cap_maxprot, &fp); + if (error != 0) goto done; if (fp->f_type == DTYPE_SHM) { handle = fp->f_data; diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 7b4b57c..53ffc72 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -602,9 +602,13 @@ vm_page_trysbusy(vm_page_t m) { u_int x; - x = m->busy_lock; - return ((x & VPB_BIT_SHARED) != 0 && - atomic_cmpset_acq_int(&m->busy_lock, x, x + VPB_ONE_SHARER)); + for (;;) { + x = m->busy_lock; + if ((x & VPB_BIT_SHARED) == 0) + return (0); + if (atomic_cmpset_acq_int(&m->busy_lock, x, x + VPB_ONE_SHARER)) + return (1); + } } /* diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c index 0730d94..c689b47 100644 --- a/sys/x86/xen/hvm.c +++ b/sys/x86/xen/hvm.c @@ -92,7 +92,7 @@ xen_hvm_init_hypercall_stubs(void) int i; base = xen_hvm_cpuid_base(); - if (!base) + if (base == 0) return (ENXIO); if (hypercall_stubs == NULL) { @@ -151,7 +151,7 @@ xen_hvm_set_callback(device_t dev) xhp.domid = DOMID_SELF; xhp.index = HVM_PARAM_CALLBACK_IRQ; - if (xen_feature(XENFEAT_hvm_callback_vector)) { + if (xen_feature(XENFEAT_hvm_callback_vector) != 0) { int error; xhp.value = HVM_CALLBACK_VECTOR(IDT_EVTCHN); @@ -161,8 +161,7 @@ xen_hvm_set_callback(device_t dev) return; } printf("Xen HVM callback vector registration failed (%d). " - "Falling back to emulated device interrupt\n", - error); + "Falling back to emulated device interrupt\n", error); } xen_vector_callback_enabled = 0; if (dev == NULL) { @@ -185,7 +184,7 @@ xen_hvm_set_callback(device_t dev) xhp.value = HVM_CALLBACK_PCI_INTX(slot, pin); } - if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp)) + if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp) != 0) panic("Can't set evtchn callback"); } @@ -216,6 +215,7 @@ xen_hvm_suspend(void) void xen_hvm_resume(void) { + xen_hvm_init_hypercall_stubs(); xen_hvm_init_shared_info_page(); } @@ -223,6 +223,7 @@ xen_hvm_resume(void) static void xen_hvm_init(void *dummy __unused) { + if (xen_hvm_init_hypercall_stubs() != 0) return; @@ -235,21 +236,20 @@ xen_hvm_init(void *dummy __unused) void xen_hvm_init_cpu(void) { - int cpu = PCPU_GET(acpi_id); - struct vcpu_info *vcpu_info; struct vcpu_register_vcpu_info info; - int rc; + struct vcpu_info *vcpu_info; + int cpu, rc; + cpu = PCPU_GET(acpi_id); vcpu_info = DPCPU_PTR(vcpu_local_info); info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT; info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info)); rc = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); - if (rc) { + if (rc != 0) DPCPU_SET(vcpu_info, &HYPERVISOR_shared_info->vcpu_info[cpu]); - } else { + else DPCPU_SET(vcpu_info, vcpu_info); - } } SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_init, NULL); |