diff options
Diffstat (limited to 'sys')
432 files changed, 10168 insertions, 3333 deletions
diff --git a/sys/amd64/amd64/gdb_machdep.c b/sys/amd64/amd64/gdb_machdep.c index 5775c8f..61ffad6 100644 --- a/sys/amd64/amd64/gdb_machdep.c +++ b/sys/amd64/amd64/gdb_machdep.c @@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$"); void * gdb_cpu_getreg(int regnum, size_t *regsz) { + static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL); + static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL); *regsz = gdb_cpu_regsz(regnum); @@ -76,6 +78,8 @@ gdb_cpu_getreg(int regnum, size_t *regsz) case 14: return (&kdb_thrctx->pcb_r14); case 15: return (&kdb_thrctx->pcb_r15); case 16: return (&kdb_thrctx->pcb_rip); + case 18: return (&_kcodesel); + case 19: return (&_kdatasel); } return (NULL); } diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 0836375..fa74eb2 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -257,8 +257,8 @@ trap(struct trapframe *frame) td->td_pticks = 0; td->td_frame = frame; addr = frame->tf_rip; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index e0fe465..97eefbf 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -17,6 +17,23 @@ profile 2 # options KDTRACE_HOOKS +# DTrace core +# NOTE: introduces CDDL-licensed components into the kernel +#device dtrace + +# DTrace modules +#device dtrace_lockstat +#device dtrace_profile +#device dtrace_sdt +#device dtrace_fbt +#device dtrace_systrace +#device dtrace_prototype +#device dtnfscl +#device dtmalloc + +# Alternatively include all the DTrace modules +#device dtraceall + ##################################################################### # SMP OPTIONS: diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index 1a4e5ab..f2de960 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -108,7 +108,6 @@ enum x2apic_state { struct vm; struct vm_exception; -struct vm_memory_segment; struct seg_desc; struct vm_exit; struct vm_run; @@ -175,17 +174,33 @@ int vm_create(const char *name, struct vm **retvm); void vm_destroy(struct vm *vm); int vm_reinit(struct vm *vm); const char *vm_name(struct vm *vm); -int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len); + +/* + * APIs that modify the guest memory map require all vcpus to be frozen. + */ +int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off, + size_t len, int prot, int flags); +int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); +void vm_free_memseg(struct vm *vm, int ident); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); -void *vm_gpa_hold(struct vm *, vm_paddr_t gpa, size_t len, int prot, - void **cookie); +int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); +int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); + +/* + * APIs that inspect the guest memory map require only a *single* vcpu to + * be frozen. This acts like a read lock on the guest memory map since any + * modification requires *all* vcpus to be frozen. + */ +int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid, + vm_ooffset_t *segoff, size_t *len, int *prot, int *flags); +int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem, + struct vm_object **objptr); +void *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len, + int prot, void **cookie); void vm_gpa_release(void *cookie); -int vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase, - struct vm_memory_segment *seg); -int vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len, - vm_offset_t *offset, struct vm_object **object); -boolean_t vm_mem_allocated(struct vm *vm, vm_paddr_t gpa); +bool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa); + int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval); int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val); int vm_get_seg_desc(struct vm *vm, int vcpu, int reg, @@ -302,8 +317,6 @@ vcpu_should_yield(struct vm *vm, int vcpu) void *vcpu_stats(struct vm *vm, int vcpu); void vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr); struct vmspace *vm_get_vmspace(struct vm *vm); -int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); -int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); struct vatpic *vm_atpic(struct vm *vm); struct vatpit *vm_atpit(struct vm *vm); struct vpmtmr *vm_pmtmr(struct vm *vm); diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index 9d031a9..1af75a3 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -34,10 +34,22 @@ void vmmdev_init(void); int vmmdev_cleanup(void); #endif -struct vm_memory_segment { - vm_paddr_t gpa; /* in */ +struct vm_memmap { + vm_paddr_t gpa; + int segid; /* memory segment */ + vm_ooffset_t segoff; /* offset into memory segment */ + size_t len; /* mmap length */ + int prot; /* RWX */ + int flags; +}; +#define VM_MEMMAP_F_WIRED 0x01 +#define VM_MEMMAP_F_IOMMU 0x02 + +#define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL) +struct vm_memseg { + int segid; size_t len; - int wired; + char name[SPECNAMELEN + 1]; }; struct vm_register { @@ -214,10 +226,14 @@ enum { IOCNUM_REINIT = 5, /* memory apis */ - IOCNUM_MAP_MEMORY = 10, - IOCNUM_GET_MEMORY_SEG = 11, + IOCNUM_MAP_MEMORY = 10, /* deprecated */ + IOCNUM_GET_MEMORY_SEG = 11, /* deprecated */ IOCNUM_GET_GPA_PMAP = 12, IOCNUM_GLA2GPA = 13, + IOCNUM_ALLOC_MEMSEG = 14, + IOCNUM_GET_MEMSEG = 15, + IOCNUM_MMAP_MEMSEG = 16, + IOCNUM_MMAP_GETNEXT = 17, /* register/state accessors */ IOCNUM_SET_REGISTER = 20, @@ -278,10 +294,14 @@ enum { _IOW('v', IOCNUM_SUSPEND, struct vm_suspend) #define VM_REINIT \ _IO('v', IOCNUM_REINIT) -#define VM_MAP_MEMORY \ - _IOWR('v', IOCNUM_MAP_MEMORY, struct vm_memory_segment) -#define VM_GET_MEMORY_SEG \ - _IOWR('v', IOCNUM_GET_MEMORY_SEG, struct vm_memory_segment) +#define VM_ALLOC_MEMSEG \ + _IOW('v', IOCNUM_ALLOC_MEMSEG, struct vm_memseg) +#define VM_GET_MEMSEG \ + _IOWR('v', IOCNUM_GET_MEMSEG, struct vm_memseg) +#define VM_MMAP_MEMSEG \ + _IOW('v', IOCNUM_MMAP_MEMSEG, struct vm_memmap) +#define VM_MMAP_GETNEXT \ + _IOWR('v', IOCNUM_MMAP_GETNEXT, struct vm_memmap) #define VM_SET_REGISTER \ _IOW('v', IOCNUM_SET_REGISTER, struct vm_register) #define VM_GET_REGISTER \ diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c index d6174e6..451e4b4 100644 --- a/sys/amd64/linux/linux_machdep.c +++ b/sys/amd64/linux/linux_machdep.c @@ -251,7 +251,7 @@ linux_mmap2(struct thread *td, struct linux_mmap2_args *args) */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - - lim_cur(p, RLIMIT_STACK); + lim_cur_proc(p, RLIMIT_STACK); PROC_UNLOCK(p); } diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index f9c11ca..1c54c5c 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -615,7 +615,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK - - lim_cur(p, RLIMIT_STACK); + lim_cur_proc(p, RLIMIT_STACK); PROC_UNLOCK(p); } diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index b25d69d..6d44801 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -1477,7 +1477,7 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit) VCPU_CTR2(svm_sc->vm, vcpu, "nested page fault with " "reserved bits set: info1(%#lx) info2(%#lx)", info1, info2); - } else if (vm_mem_allocated(svm_sc->vm, info2)) { + } else if (vm_mem_allocated(svm_sc->vm, vcpu, info2)) { vmexit->exitcode = VM_EXITCODE_PAGING; vmexit->u.paging.gpa = info2; vmexit->u.paging.fault_type = npf_fault_type(info1); diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index f590586..517a374 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -2425,7 +2425,7 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) * this must be an instruction that accesses MMIO space. */ gpa = vmcs_gpa(); - if (vm_mem_allocated(vmx->vm, gpa) || + if (vm_mem_allocated(vmx->vm, vcpu, gpa) || apic_access_fault(vmx, vcpu, gpa)) { vmexit->exitcode = VM_EXITCODE_PAGING; vmexit->inst_length = 0; diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index b789f77..692190a 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -76,11 +76,17 @@ struct pptintr_arg { /* pptintr(pptintr_arg) */ uint64_t msg_data; }; +struct pptseg { + vm_paddr_t gpa; + size_t len; + int wired; +}; + struct pptdev { device_t dev; struct vm *vm; /* owner of this device */ TAILQ_ENTRY(pptdev) next; - struct vm_memory_segment mmio[MAX_MMIOSEGS]; + struct pptseg mmio[MAX_MMIOSEGS]; struct { int num_msgs; /* guest state */ @@ -207,14 +213,14 @@ static void ppt_unmap_mmio(struct vm *vm, struct pptdev *ppt) { int i; - struct vm_memory_segment *seg; + struct pptseg *seg; for (i = 0; i < MAX_MMIOSEGS; i++) { seg = &ppt->mmio[i]; if (seg->len == 0) continue; (void)vm_unmap_mmio(vm, seg->gpa, seg->len); - bzero(seg, sizeof(struct vm_memory_segment)); + bzero(seg, sizeof(struct pptseg)); } } @@ -324,7 +330,7 @@ ppt_is_mmio(struct vm *vm, vm_paddr_t gpa) { int i; struct pptdev *ppt; - struct vm_memory_segment *seg; + struct pptseg *seg; TAILQ_FOREACH(ppt, &pptdev_list, next) { if (ppt->vm != vm) @@ -410,7 +416,7 @@ ppt_map_mmio(struct vm *vm, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa) { int i, error; - struct vm_memory_segment *seg; + struct pptseg *seg; struct pptdev *ppt; ppt = ppt_find(bus, slot, func); diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 2c37a1a..0987059 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -119,12 +119,21 @@ struct vcpu { #define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED) struct mem_seg { + size_t len; + bool sysmem; + struct vm_object *object; +}; +#define VM_MAX_MEMSEGS 2 + +struct mem_map { vm_paddr_t gpa; size_t len; - boolean_t wired; - vm_object_t object; + vm_ooffset_t segoff; + int segid; + int prot; + int flags; }; -#define VM_MAX_MEMORY_SEGMENTS 2 +#define VM_MAX_MEMMAPS 4 /* * Initialization: @@ -150,8 +159,8 @@ struct vm { void *rendezvous_arg; /* (x) rendezvous func/arg */ vm_rendezvous_func_t rendezvous_func; struct mtx rendezvous_mtx; /* (o) rendezvous lock */ - int num_mem_segs; /* (o) guest memory segments */ - struct mem_seg mem_segs[VM_MAX_MEMORY_SEGMENTS]; + struct mem_map mem_maps[VM_MAX_MEMMAPS]; /* (i) guest address space */ + struct mem_seg mem_segs[VM_MAX_MEMSEGS]; /* (o) guest memory regions */ struct vmspace *vmspace; /* (o) guest's address space */ char name[VM_MAX_NAMELEN]; /* (o) virtual machine name */ struct vcpu vcpu[VM_MAXCPU]; /* (i) guest vcpus */ @@ -222,6 +231,8 @@ TUNABLE_INT("hw.vmm.force_iommu", &vmm_force_iommu); SYSCTL_INT(_hw_vmm, OID_AUTO, force_iommu, CTLFLAG_RDTUN, &vmm_force_iommu, 0, "Force use of I/O MMU even if no passthrough devices were found."); +static void vm_free_memmap(struct vm *vm, int ident); +static bool sysmem_mapping(struct vm *vm, struct mem_map *mm); static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr); #ifdef KTR @@ -442,7 +453,6 @@ vm_create(const char *name, struct vm **retvm) vm = malloc(sizeof(struct vm), M_VM, M_WAITOK | M_ZERO); strcpy(vm->name, name); - vm->num_mem_segs = 0; vm->vmspace = vmspace; mtx_init(&vm->rendezvous_mtx, "vm rendezvous lock", 0, MTX_DEF); @@ -453,18 +463,9 @@ vm_create(const char *name, struct vm **retvm) } static void -vm_free_mem_seg(struct vm *vm, struct mem_seg *seg) -{ - - if (seg->object != NULL) - vmm_mem_free(vm->vmspace, seg->gpa, seg->len); - - bzero(seg, sizeof(*seg)); -} - -static void vm_cleanup(struct vm *vm, bool destroy) { + struct mem_map *mm; int i; ppt_unassign_all(vm); @@ -487,11 +488,23 @@ vm_cleanup(struct vm *vm, bool destroy) VMCLEANUP(vm->cookie); - if (destroy) { - for (i = 0; i < vm->num_mem_segs; i++) - vm_free_mem_seg(vm, &vm->mem_segs[i]); + /* + * System memory is removed from the guest address space only when + * the VM is destroyed. This is because the mapping remains the same + * across VM reset. + * + * Device memory can be relocated by the guest (e.g. using PCI BARs) + * so those mappings are removed on a VM reset. + */ + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (destroy || !sysmem_mapping(vm, mm)) + vm_free_memmap(vm, i); + } - vm->num_mem_segs = 0; + if (destroy) { + for (i = 0; i < VM_MAX_MEMSEGS; i++) + vm_free_memseg(vm, i); VMSPACE_FREE(vm->vmspace); vm->vmspace = NULL; @@ -549,146 +562,243 @@ vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len) return (0); } -boolean_t -vm_mem_allocated(struct vm *vm, vm_paddr_t gpa) +/* + * Return 'true' if 'gpa' is allocated in the guest address space. + * + * This function is called in the context of a running vcpu which acts as + * an implicit lock on 'vm->mem_maps[]'. + */ +bool +vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa) { + struct mem_map *mm; int i; - vm_paddr_t gpabase, gpalimit; - for (i = 0; i < vm->num_mem_segs; i++) { - gpabase = vm->mem_segs[i].gpa; - gpalimit = gpabase + vm->mem_segs[i].len; - if (gpa >= gpabase && gpa < gpalimit) - return (TRUE); /* 'gpa' is regular memory */ +#ifdef INVARIANTS + int hostcpu, state; + state = vcpu_get_state(vm, vcpuid, &hostcpu); + KASSERT(state == VCPU_RUNNING && hostcpu == curcpu, + ("%s: invalid vcpu state %d/%d", __func__, state, hostcpu)); +#endif + + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (mm->len != 0 && gpa >= mm->gpa && gpa < mm->gpa + mm->len) + return (true); /* 'gpa' is sysmem or devmem */ } if (ppt_is_mmio(vm, gpa)) - return (TRUE); /* 'gpa' is pci passthru mmio */ + return (true); /* 'gpa' is pci passthru mmio */ - return (FALSE); + return (false); } int -vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len) +vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem) { - int available, allocated; struct mem_seg *seg; - vm_object_t object; - vm_paddr_t g; + vm_object_t obj; - if ((gpa & PAGE_MASK) || (len & PAGE_MASK) || len == 0) + if (ident < 0 || ident >= VM_MAX_MEMSEGS) return (EINVAL); - - available = allocated = 0; - g = gpa; - while (g < gpa + len) { - if (vm_mem_allocated(vm, g)) - allocated++; - else - available++; - g += PAGE_SIZE; - } - - /* - * If there are some allocated and some available pages in the address - * range then it is an error. - */ - if (allocated && available) + if (len == 0 || (len & PAGE_MASK)) return (EINVAL); - /* - * If the entire address range being requested has already been - * allocated then there isn't anything more to do. - */ - if (allocated && available == 0) - return (0); - - if (vm->num_mem_segs >= VM_MAX_MEMORY_SEGMENTS) - return (E2BIG); - - seg = &vm->mem_segs[vm->num_mem_segs]; + seg = &vm->mem_segs[ident]; + if (seg->object != NULL) { + if (seg->len == len && seg->sysmem == sysmem) + return (EEXIST); + else + return (EINVAL); + } - if ((object = vmm_mem_alloc(vm->vmspace, gpa, len)) == NULL) + obj = vm_object_allocate(OBJT_DEFAULT, len >> PAGE_SHIFT); + if (obj == NULL) return (ENOMEM); - seg->gpa = gpa; seg->len = len; - seg->object = object; - seg->wired = FALSE; + seg->object = obj; + seg->sysmem = sysmem; + return (0); +} - vm->num_mem_segs++; +int +vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem, + vm_object_t *objptr) +{ + struct mem_seg *seg; + + if (ident < 0 || ident >= VM_MAX_MEMSEGS) + return (EINVAL); + seg = &vm->mem_segs[ident]; + if (len) + *len = seg->len; + if (sysmem) + *sysmem = seg->sysmem; + if (objptr) + *objptr = seg->object; return (0); } -static vm_paddr_t -vm_maxmem(struct vm *vm) +void +vm_free_memseg(struct vm *vm, int ident) { - int i; - vm_paddr_t gpa, maxmem; + struct mem_seg *seg; - maxmem = 0; - for (i = 0; i < vm->num_mem_segs; i++) { - gpa = vm->mem_segs[i].gpa + vm->mem_segs[i].len; - if (gpa > maxmem) - maxmem = gpa; + KASSERT(ident >= 0 && ident < VM_MAX_MEMSEGS, + ("%s: invalid memseg ident %d", __func__, ident)); + + seg = &vm->mem_segs[ident]; + if (seg->object != NULL) { + vm_object_deallocate(seg->object); + bzero(seg, sizeof(struct mem_seg)); } - return (maxmem); } -static void -vm_gpa_unwire(struct vm *vm) +int +vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t first, + size_t len, int prot, int flags) { - int i, rv; struct mem_seg *seg; + struct mem_map *m, *map; + vm_ooffset_t last; + int i, error; - for (i = 0; i < vm->num_mem_segs; i++) { - seg = &vm->mem_segs[i]; - if (!seg->wired) - continue; + if (prot == 0 || (prot & ~(VM_PROT_ALL)) != 0) + return (EINVAL); + + if (flags & ~VM_MEMMAP_F_WIRED) + return (EINVAL); + + if (segid < 0 || segid >= VM_MAX_MEMSEGS) + return (EINVAL); - rv = vm_map_unwire(&vm->vmspace->vm_map, - seg->gpa, seg->gpa + seg->len, - VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); - KASSERT(rv == KERN_SUCCESS, ("vm(%s) memory segment " - "%#lx/%ld could not be unwired: %d", - vm_name(vm), seg->gpa, seg->len, rv)); + seg = &vm->mem_segs[segid]; + if (seg->object == NULL) + return (EINVAL); + + last = first + len; + if (first < 0 || first >= last || last > seg->len) + return (EINVAL); + + if ((gpa | first | last) & PAGE_MASK) + return (EINVAL); + + map = NULL; + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + m = &vm->mem_maps[i]; + if (m->len == 0) { + map = m; + break; + } + } - seg->wired = FALSE; + if (map == NULL) + return (ENOSPC); + + error = vm_map_find(&vm->vmspace->vm_map, seg->object, first, &gpa, + len, 0, VMFS_NO_SPACE, prot, prot, 0); + if (error != KERN_SUCCESS) + return (EFAULT); + + vm_object_reference(seg->object); + + if (flags & VM_MEMMAP_F_WIRED) { + error = vm_map_wire(&vm->vmspace->vm_map, gpa, gpa + len, + VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); + if (error != KERN_SUCCESS) { + vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len); + return (EFAULT); + } } + + map->gpa = gpa; + map->len = len; + map->segoff = first; + map->segid = segid; + map->prot = prot; + map->flags = flags; + return (0); } -static int -vm_gpa_wire(struct vm *vm) +int +vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid, + vm_ooffset_t *segoff, size_t *len, int *prot, int *flags) { - int i, rv; - struct mem_seg *seg; + struct mem_map *mm, *mmnext; + int i; - for (i = 0; i < vm->num_mem_segs; i++) { - seg = &vm->mem_segs[i]; - if (seg->wired) + mmnext = NULL; + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (mm->len == 0 || mm->gpa < *gpa) continue; + if (mmnext == NULL || mm->gpa < mmnext->gpa) + mmnext = mm; + } - /* XXX rlimits? */ - rv = vm_map_wire(&vm->vmspace->vm_map, - seg->gpa, seg->gpa + seg->len, - VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); - if (rv != KERN_SUCCESS) - break; - - seg->wired = TRUE; + if (mmnext != NULL) { + *gpa = mmnext->gpa; + if (segid) + *segid = mmnext->segid; + if (segoff) + *segoff = mmnext->segoff; + if (len) + *len = mmnext->len; + if (prot) + *prot = mmnext->prot; + if (flags) + *flags = mmnext->flags; + return (0); + } else { + return (ENOENT); } +} - if (i < vm->num_mem_segs) { - /* - * Undo the wiring before returning an error. - */ - vm_gpa_unwire(vm); - return (EAGAIN); +static void +vm_free_memmap(struct vm *vm, int ident) +{ + struct mem_map *mm; + int error; + + mm = &vm->mem_maps[ident]; + if (mm->len) { + error = vm_map_remove(&vm->vmspace->vm_map, mm->gpa, + mm->gpa + mm->len); + KASSERT(error == KERN_SUCCESS, ("%s: vm_map_remove error %d", + __func__, error)); + bzero(mm, sizeof(struct mem_map)); } +} - return (0); +static __inline bool +sysmem_mapping(struct vm *vm, struct mem_map *mm) +{ + + if (mm->len != 0 && vm->mem_segs[mm->segid].sysmem) + return (true); + else + return (false); +} + +static vm_paddr_t +sysmem_maxaddr(struct vm *vm) +{ + struct mem_map *mm; + vm_paddr_t maxaddr; + int i; + + maxaddr = 0; + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (sysmem_mapping(vm, mm)) { + if (maxaddr < mm->gpa + mm->len) + maxaddr = mm->gpa + mm->len; + } + } + return (maxaddr); } static void @@ -696,20 +806,36 @@ vm_iommu_modify(struct vm *vm, boolean_t map) { int i, sz; vm_paddr_t gpa, hpa; - struct mem_seg *seg; + struct mem_map *mm; void *vp, *cookie, *host_domain; sz = PAGE_SIZE; host_domain = iommu_host_domain(); - for (i = 0; i < vm->num_mem_segs; i++) { - seg = &vm->mem_segs[i]; - KASSERT(seg->wired, ("vm(%s) memory segment %#lx/%ld not wired", - vm_name(vm), seg->gpa, seg->len)); + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (!sysmem_mapping(vm, mm)) + continue; - gpa = seg->gpa; - while (gpa < seg->gpa + seg->len) { - vp = vm_gpa_hold(vm, gpa, PAGE_SIZE, VM_PROT_WRITE, + if (map) { + KASSERT((mm->flags & VM_MEMMAP_F_IOMMU) == 0, + ("iommu map found invalid memmap %#lx/%#lx/%#x", + mm->gpa, mm->len, mm->flags)); + if ((mm->flags & VM_MEMMAP_F_WIRED) == 0) + continue; + mm->flags |= VM_MEMMAP_F_IOMMU; + } else { + if ((mm->flags & VM_MEMMAP_F_IOMMU) == 0) + continue; + mm->flags &= ~VM_MEMMAP_F_IOMMU; + KASSERT((mm->flags & VM_MEMMAP_F_WIRED) != 0, + ("iommu unmap found invalid memmap %#lx/%#lx/%#x", + mm->gpa, mm->len, mm->flags)); + } + + gpa = mm->gpa; + while (gpa < mm->gpa + mm->len) { + vp = vm_gpa_hold(vm, -1, gpa, PAGE_SIZE, VM_PROT_WRITE, &cookie); KASSERT(vp != NULL, ("vm(%s) could not map gpa %#lx", vm_name(vm), gpa)); @@ -751,10 +877,9 @@ vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func) if (error) return (error); - if (ppt_assigned_devices(vm) == 0) { + if (ppt_assigned_devices(vm) == 0) vm_iommu_unmap(vm); - vm_gpa_unwire(vm); - } + return (0); } @@ -764,23 +889,12 @@ vm_assign_pptdev(struct vm *vm, int bus, int slot, int func) int error; vm_paddr_t maxaddr; - /* - * Virtual machines with pci passthru devices get special treatment: - * - the guest physical memory is wired - * - the iommu is programmed to do the 'gpa' to 'hpa' translation - * - * We need to do this before the first pci passthru device is attached. - */ + /* Set up the IOMMU to do the 'gpa' to 'hpa' translation */ if (ppt_assigned_devices(vm) == 0) { KASSERT(vm->iommu == NULL, ("vm_assign_pptdev: iommu must be NULL")); - maxaddr = vm_maxmem(vm); + maxaddr = sysmem_maxaddr(vm); vm->iommu = iommu_create_domain(maxaddr); - - error = vm_gpa_wire(vm); - if (error) - return (error); - vm_iommu_map(vm); } @@ -789,18 +903,43 @@ vm_assign_pptdev(struct vm *vm, int bus, int slot, int func) } void * -vm_gpa_hold(struct vm *vm, vm_paddr_t gpa, size_t len, int reqprot, +vm_gpa_hold(struct vm *vm, int vcpuid, vm_paddr_t gpa, size_t len, int reqprot, void **cookie) { - int count, pageoff; + int i, count, pageoff; + struct mem_map *mm; vm_page_t m; - +#ifdef INVARIANTS + /* + * All vcpus are frozen by ioctls that modify the memory map + * (e.g. VM_MMAP_MEMSEG). Therefore 'vm->memmap[]' stability is + * guaranteed if at least one vcpu is in the VCPU_FROZEN state. + */ + int state; + KASSERT(vcpuid >= -1 || vcpuid < VM_MAXCPU, ("%s: invalid vcpuid %d", + __func__, vcpuid)); + for (i = 0; i < VM_MAXCPU; i++) { + if (vcpuid != -1 && vcpuid != i) + continue; + state = vcpu_get_state(vm, i, NULL); + KASSERT(state == VCPU_FROZEN, ("%s: invalid vcpu state %d", + __func__, state)); + } +#endif pageoff = gpa & PAGE_MASK; if (len > PAGE_SIZE - pageoff) panic("vm_gpa_hold: invalid gpa/len: 0x%016lx/%lu", gpa, len); - count = vm_fault_quick_hold_pages(&vm->vmspace->vm_map, - trunc_page(gpa), PAGE_SIZE, reqprot, &m, 1); + count = 0; + for (i = 0; i < VM_MAX_MEMMAPS; i++) { + mm = &vm->mem_maps[i]; + if (sysmem_mapping(vm, mm) && gpa >= mm->gpa && + gpa < mm->gpa + mm->len) { + count = vm_fault_quick_hold_pages(&vm->vmspace->vm_map, + trunc_page(gpa), PAGE_SIZE, reqprot, &m, 1); + break; + } + } if (count == 1) { *cookie = m; @@ -822,50 +961,6 @@ vm_gpa_release(void *cookie) } int -vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase, - struct vm_memory_segment *seg) -{ - int i; - - for (i = 0; i < vm->num_mem_segs; i++) { - if (gpabase == vm->mem_segs[i].gpa) { - seg->gpa = vm->mem_segs[i].gpa; - seg->len = vm->mem_segs[i].len; - seg->wired = vm->mem_segs[i].wired; - return (0); - } - } - return (-1); -} - -int -vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len, - vm_offset_t *offset, struct vm_object **object) -{ - int i; - size_t seg_len; - vm_paddr_t seg_gpa; - vm_object_t seg_obj; - - for (i = 0; i < vm->num_mem_segs; i++) { - if ((seg_obj = vm->mem_segs[i].object) == NULL) - continue; - - seg_gpa = vm->mem_segs[i].gpa; - seg_len = vm->mem_segs[i].len; - - if (gpa >= seg_gpa && gpa < seg_gpa + seg_len) { - *offset = gpa - seg_gpa; - *object = seg_obj; - vm_object_reference(seg_obj); - return (0); - } - } - - return (EINVAL); -} - -int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval) { @@ -2423,8 +2518,8 @@ vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, } for (idx = 0; idx < nused; idx++) { - hva = vm_gpa_hold(vm, copyinfo[idx].gpa, copyinfo[idx].len, - prot, &cookie); + hva = vm_gpa_hold(vm, vcpuid, copyinfo[idx].gpa, + copyinfo[idx].len, prot, &cookie); if (hva == NULL) break; copyinfo[idx].hva = hva; diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index e3e140a..4ef1482 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_map.h> +#include <vm/vm_object.h> #include <machine/vmparam.h> #include <machine/vmm.h> @@ -60,10 +61,19 @@ __FBSDID("$FreeBSD$"); #include "io/vhpet.h" #include "io/vrtc.h" +struct devmem_softc { + int segid; + char *name; + struct cdev *cdev; + struct vmmdev_softc *sc; + SLIST_ENTRY(devmem_softc) link; +}; + struct vmmdev_softc { struct vm *vm; /* vm instance cookie */ struct cdev *cdev; SLIST_ENTRY(vmmdev_softc) link; + SLIST_HEAD(, devmem_softc) devmem; int flags; }; #define VSC_LINKED 0x01 @@ -76,6 +86,63 @@ static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev"); SYSCTL_DECL(_hw_vmm); +static int devmem_create_cdev(const char *vmname, int id, char *devmem); +static void devmem_destroy(void *arg); + +static int +vcpu_lock_one(struct vmmdev_softc *sc, int vcpu) +{ + int error; + + if (vcpu < 0 || vcpu >= VM_MAXCPU) + return (EINVAL); + + error = vcpu_set_state(sc->vm, vcpu, VCPU_FROZEN, true); + return (error); +} + +static void +vcpu_unlock_one(struct vmmdev_softc *sc, int vcpu) +{ + enum vcpu_state state; + + state = vcpu_get_state(sc->vm, vcpu, NULL); + if (state != VCPU_FROZEN) { + panic("vcpu %s(%d) has invalid state %d", vm_name(sc->vm), + vcpu, state); + } + + vcpu_set_state(sc->vm, vcpu, VCPU_IDLE, false); +} + +static int +vcpu_lock_all(struct vmmdev_softc *sc) +{ + int error, vcpu; + + for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) { + error = vcpu_lock_one(sc, vcpu); + if (error) + break; + } + + if (error) { + while (--vcpu >= 0) + vcpu_unlock_one(sc, vcpu); + } + + return (error); +} + +static void +vcpu_unlock_all(struct vmmdev_softc *sc) +{ + int vcpu; + + for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) + vcpu_unlock_one(sc, vcpu); +} + static struct vmmdev_softc * vmmdev_lookup(const char *name) { @@ -108,12 +175,16 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags) void *hpa, *cookie; struct vmmdev_softc *sc; - static char zerobuf[PAGE_SIZE]; - - error = 0; sc = vmmdev_lookup2(cdev); if (sc == NULL) - error = ENXIO; + return (ENXIO); + + /* + * Get a read lock on the guest memory map by freezing any vcpu. + */ + error = vcpu_lock_one(sc, VM_MAXCPU - 1); + if (error) + return (error); prot = (uio->uio_rw == UIO_WRITE ? VM_PROT_WRITE : VM_PROT_READ); while (uio->uio_resid > 0 && error == 0) { @@ -129,10 +200,11 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags) * Since this device does not support lseek(2), dd(1) will * read(2) blocks of data to simulate the lseek(2). */ - hpa = vm_gpa_hold(sc->vm, gpa, c, prot, &cookie); + hpa = vm_gpa_hold(sc->vm, VM_MAXCPU - 1, gpa, c, prot, &cookie); if (hpa == NULL) { if (uio->uio_rw == UIO_READ) - error = uiomove(zerobuf, c, uio); + error = uiomove(__DECONST(void *, zero_region), + c, uio); else error = EFAULT; } else { @@ -140,6 +212,70 @@ vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags) vm_gpa_release(cookie); } } + vcpu_unlock_one(sc, VM_MAXCPU - 1); + return (error); +} + +CTASSERT(sizeof(((struct vm_memseg *)0)->name) >= SPECNAMELEN + 1); + +static int +get_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg) +{ + struct devmem_softc *dsc; + int error; + bool sysmem; + + error = vm_get_memseg(sc->vm, mseg->segid, &mseg->len, &sysmem, NULL); + if (error || mseg->len == 0) + return (error); + + if (!sysmem) { + SLIST_FOREACH(dsc, &sc->devmem, link) { + if (dsc->segid == mseg->segid) + break; + } + KASSERT(dsc != NULL, ("%s: devmem segment %d not found", + __func__, mseg->segid)); + error = copystr(dsc->name, mseg->name, SPECNAMELEN + 1, NULL); + } else { + bzero(mseg->name, sizeof(mseg->name)); + } + + return (error); +} + +static int +alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg) +{ + char *name; + int error; + bool sysmem; + + error = 0; + name = NULL; + sysmem = true; + + if (VM_MEMSEG_NAME(mseg)) { + sysmem = false; + name = malloc(SPECNAMELEN + 1, M_VMMDEV, M_WAITOK); + error = copystr(VM_MEMSEG_NAME(mseg), name, SPECNAMELEN + 1, 0); + if (error) + goto done; + } + + error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, sysmem); + if (error) + goto done; + + if (VM_MEMSEG_NAME(mseg)) { + error = devmem_create_cdev(vm_name(sc->vm), mseg->segid, name); + if (error) + vm_free_memseg(sc->vm, mseg->segid); + else + name = NULL; /* freed when 'cdev' is destroyed */ + } +done: + free(name, M_VMMDEV); return (error); } @@ -150,7 +286,6 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, int error, vcpu, state_changed, size; cpuset_t *cpuset; struct vmmdev_softc *sc; - struct vm_memory_segment *seg; struct vm_register *vmreg; struct vm_seg_desc *vmsegdesc; struct vm_run *vmrun; @@ -177,6 +312,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct vm_intinfo *vmii; struct vm_rtc_time *rtctime; struct vm_rtc_data *rtcdata; + struct vm_memmap *mm; sc = vmmdev_lookup2(cdev); if (sc == NULL) @@ -211,43 +347,41 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, * Assumes that the first field of the ioctl data is the vcpu. */ vcpu = *(int *)data; - if (vcpu < 0 || vcpu >= VM_MAXCPU) { - error = EINVAL; - goto done; - } - - error = vcpu_set_state(sc->vm, vcpu, VCPU_FROZEN, true); + error = vcpu_lock_one(sc, vcpu); if (error) goto done; - state_changed = 1; break; case VM_MAP_PPTDEV_MMIO: case VM_BIND_PPTDEV: case VM_UNBIND_PPTDEV: - case VM_MAP_MEMORY: + case VM_ALLOC_MEMSEG: + case VM_MMAP_MEMSEG: case VM_REINIT: /* * ioctls that operate on the entire virtual machine must * prevent all vcpus from running. */ - error = 0; - for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) { - error = vcpu_set_state(sc->vm, vcpu, VCPU_FROZEN, true); - if (error) - break; - } - - if (error) { - while (--vcpu >= 0) - vcpu_set_state(sc->vm, vcpu, VCPU_IDLE, false); + error = vcpu_lock_all(sc); + if (error) goto done; - } - state_changed = 2; break; + case VM_GET_MEMSEG: + case VM_MMAP_GETNEXT: + /* + * Lock a vcpu to make sure that the memory map cannot be + * modified while it is being inspected. + */ + vcpu = VM_MAXCPU - 1; + error = vcpu_lock_one(sc, vcpu); + if (error) + goto done; + state_changed = 1; + break; + default: break; } @@ -372,15 +506,21 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, error = vatpic_set_irq_trigger(sc->vm, isa_irq_trigger->atpic_irq, isa_irq_trigger->trigger); break; - case VM_MAP_MEMORY: - seg = (struct vm_memory_segment *)data; - error = vm_malloc(sc->vm, seg->gpa, seg->len); + case VM_MMAP_GETNEXT: + mm = (struct vm_memmap *)data; + error = vm_mmap_getnext(sc->vm, &mm->gpa, &mm->segid, + &mm->segoff, &mm->len, &mm->prot, &mm->flags); break; - case VM_GET_MEMORY_SEG: - seg = (struct vm_memory_segment *)data; - seg->len = 0; - (void)vm_gpabase2memseg(sc->vm, seg->gpa, seg); - error = 0; + case VM_MMAP_MEMSEG: + mm = (struct vm_memmap *)data; + error = vm_mmap_memseg(sc->vm, mm->gpa, mm->segid, mm->segoff, + mm->len, mm->prot, mm->flags); + break; + case VM_ALLOC_MEMSEG: + error = alloc_memseg(sc, (struct vm_memseg *)data); + break; + case VM_GET_MEMSEG: + error = get_memseg(sc, (struct vm_memseg *)data); break; case VM_GET_REGISTER: vmreg = (struct vm_register *)data; @@ -505,12 +645,10 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, break; } - if (state_changed == 1) { - vcpu_set_state(sc->vm, vcpu, VCPU_IDLE, false); - } else if (state_changed == 2) { - for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) - vcpu_set_state(sc->vm, vcpu, VCPU_IDLE, false); - } + if (state_changed == 1) + vcpu_unlock_one(sc, vcpu); + else if (state_changed == 2) + vcpu_unlock_all(sc); done: /* Make sure that no handler returns a bogus value like ERESTART */ @@ -519,26 +657,79 @@ done: } static int -vmmdev_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, - vm_size_t size, struct vm_object **object, int nprot) +vmmdev_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t mapsize, + struct vm_object **objp, int nprot) { - int error; struct vmmdev_softc *sc; + vm_paddr_t gpa; + size_t len; + vm_ooffset_t segoff, first, last; + int error, found, segid; + bool sysmem; + + first = *offset; + last = first + mapsize; + if ((nprot & PROT_EXEC) || first < 0 || first >= last) + return (EINVAL); sc = vmmdev_lookup2(cdev); - if (sc != NULL && (nprot & PROT_EXEC) == 0) - error = vm_get_memobj(sc->vm, *offset, size, offset, object); - else - error = EINVAL; + if (sc == NULL) { + /* virtual machine is in the process of being created */ + return (EINVAL); + } + /* + * Get a read lock on the guest memory map by freezing any vcpu. + */ + error = vcpu_lock_one(sc, VM_MAXCPU - 1); + if (error) + return (error); + + gpa = 0; + found = 0; + while (!found) { + error = vm_mmap_getnext(sc->vm, &gpa, &segid, &segoff, &len, + NULL, NULL); + if (error) + break; + + if (first >= gpa && last <= gpa + len) + found = 1; + else + gpa += len; + } + + if (found) { + error = vm_get_memseg(sc->vm, segid, &len, &sysmem, objp); + KASSERT(error == 0 && *objp != NULL, + ("%s: invalid memory segment %d", __func__, segid)); + if (sysmem) { + vm_object_reference(*objp); + *offset = segoff + (first - gpa); + } else { + error = EINVAL; + } + } + vcpu_unlock_one(sc, VM_MAXCPU - 1); return (error); } static void vmmdev_destroy(void *arg) { - struct vmmdev_softc *sc = arg; + struct devmem_softc *dsc; + int error; + + error = vcpu_lock_all(sc); + KASSERT(error == 0, ("%s: error %d freezing vcpus", __func__, error)); + + while ((dsc = SLIST_FIRST(&sc->devmem)) != NULL) { + KASSERT(dsc->cdev == NULL, ("%s: devmem not free", __func__)); + SLIST_REMOVE_HEAD(&sc->devmem, link); + free(dsc->name, M_VMMDEV); + free(dsc, M_VMMDEV); + } if (sc->cdev != NULL) destroy_dev(sc->cdev); @@ -560,6 +751,7 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS) { int error; char buf[VM_MAX_NAMELEN]; + struct devmem_softc *dsc; struct vmmdev_softc *sc; struct cdev *cdev; @@ -578,22 +770,30 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS) /* * The 'cdev' will be destroyed asynchronously when 'si_threadcount' * goes down to 0 so we should not do it again in the callback. + * + * Setting 'sc->cdev' to NULL is also used to indicate that the VM + * is scheduled for destruction. */ cdev = sc->cdev; sc->cdev = NULL; mtx_unlock(&vmmdev_mtx); /* - * Schedule the 'cdev' to be destroyed: + * Schedule all cdevs to be destroyed: * - * - any new operations on this 'cdev' will return an error (ENXIO). + * - any new operations on the 'cdev' will return an error (ENXIO). * * - when the 'si_threadcount' dwindles down to zero the 'cdev' will * be destroyed and the callback will be invoked in a taskqueue * context. + * + * - the 'devmem' cdevs are destroyed before the virtual machine 'cdev' */ + SLIST_FOREACH(dsc, &sc->devmem, link) { + KASSERT(dsc->cdev != NULL, ("devmem cdev already destroyed")); + destroy_dev_sched_cb(dsc->cdev, devmem_destroy, dsc); + } destroy_dev_sched_cb(cdev, vmmdev_destroy, sc); - return (0); } SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy, CTLTYPE_STRING | CTLFLAG_RW, @@ -634,6 +834,7 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS) sc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO); sc->vm = vm; + SLIST_INIT(&sc->devmem); /* * Lookup the name again just in case somebody sneaked in when we @@ -687,3 +888,96 @@ vmmdev_cleanup(void) return (error); } + +static int +devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len, + struct vm_object **objp, int nprot) +{ + struct devmem_softc *dsc; + vm_ooffset_t first, last; + size_t seglen; + int error; + bool sysmem; + + dsc = cdev->si_drv1; + if (dsc == NULL) { + /* 'cdev' has been created but is not ready for use */ + return (ENXIO); + } + + first = *offset; + last = *offset + len; + if ((nprot & PROT_EXEC) || first < 0 || first >= last) + return (EINVAL); + + error = vcpu_lock_one(dsc->sc, VM_MAXCPU - 1); + if (error) + return (error); + + error = vm_get_memseg(dsc->sc->vm, dsc->segid, &seglen, &sysmem, objp); + KASSERT(error == 0 && !sysmem && *objp != NULL, + ("%s: invalid devmem segment %d", __func__, dsc->segid)); + + vcpu_unlock_one(dsc->sc, VM_MAXCPU - 1); + + if (seglen >= last) { + vm_object_reference(*objp); + return (0); + } else { + return (EINVAL); + } +} + +static struct cdevsw devmemsw = { + .d_name = "devmem", + .d_version = D_VERSION, + .d_mmap_single = devmem_mmap_single, +}; + +static int +devmem_create_cdev(const char *vmname, int segid, char *devname) +{ + struct devmem_softc *dsc; + struct vmmdev_softc *sc; + struct cdev *cdev; + int error; + + error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &devmemsw, NULL, + UID_ROOT, GID_WHEEL, 0600, "vmm/%s.%s", vmname, devname); + if (error) + return (error); + + dsc = malloc(sizeof(struct devmem_softc), M_VMMDEV, M_WAITOK | M_ZERO); + + mtx_lock(&vmmdev_mtx); + sc = vmmdev_lookup(vmname); + KASSERT(sc != NULL, ("%s: vm %s softc not found", __func__, vmname)); + if (sc->cdev == NULL) { + /* virtual machine is being created or destroyed */ + mtx_unlock(&vmmdev_mtx); + free(dsc, M_VMMDEV); + destroy_dev_sched_cb(cdev, NULL, 0); + return (ENODEV); + } + + dsc->segid = segid; + dsc->name = devname; + dsc->cdev = cdev; + dsc->sc = sc; + SLIST_INSERT_HEAD(&sc->devmem, dsc, link); + mtx_unlock(&vmmdev_mtx); + + /* The 'cdev' is ready for use after 'si_drv1' is initialized */ + cdev->si_drv1 = dsc; + return (0); +} + +static void +devmem_destroy(void *arg) +{ + struct devmem_softc *dsc = arg; + + KASSERT(dsc->cdev, ("%s: devmem cdev already destroyed", __func__)); + dsc->cdev = NULL; + dsc->sc = NULL; +} diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 758b7e8..6dadcc1 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -1677,12 +1677,12 @@ ptp_release(void **cookie) } static void * -ptp_hold(struct vm *vm, vm_paddr_t ptpphys, size_t len, void **cookie) +ptp_hold(struct vm *vm, int vcpu, vm_paddr_t ptpphys, size_t len, void **cookie) { void *ptr; ptp_release(cookie); - ptr = vm_gpa_hold(vm, ptpphys, len, VM_PROT_RW, cookie); + ptr = vm_gpa_hold(vm, vcpu, ptpphys, len, VM_PROT_RW, cookie); return (ptr); } @@ -1729,7 +1729,8 @@ restart: /* Zero out the lower 12 bits. */ ptpphys &= ~0xfff; - ptpbase32 = ptp_hold(vm, ptpphys, PAGE_SIZE, &cookie); + ptpbase32 = ptp_hold(vm, vcpuid, ptpphys, PAGE_SIZE, + &cookie); if (ptpbase32 == NULL) goto error; @@ -1788,7 +1789,8 @@ restart: /* Zero out the lower 5 bits and the upper 32 bits */ ptpphys &= 0xffffffe0UL; - ptpbase = ptp_hold(vm, ptpphys, sizeof(*ptpbase) * 4, &cookie); + ptpbase = ptp_hold(vm, vcpuid, ptpphys, sizeof(*ptpbase) * 4, + &cookie); if (ptpbase == NULL) goto error; @@ -1811,7 +1813,7 @@ restart: /* Zero out the lower 12 bits and the upper 12 bits */ ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12; - ptpbase = ptp_hold(vm, ptpphys, PAGE_SIZE, &cookie); + ptpbase = ptp_hold(vm, vcpuid, ptpphys, PAGE_SIZE, &cookie); if (ptpbase == NULL) goto error; diff --git a/sys/amd64/vmm/vmm_mem.c b/sys/amd64/vmm/vmm_mem.c index 1019f2b..c9be6c9 100644 --- a/sys/amd64/vmm/vmm_mem.c +++ b/sys/amd64/vmm/vmm_mem.c @@ -114,38 +114,6 @@ vmm_mmio_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) vm_map_remove(&vmspace->vm_map, gpa, gpa + len); } -vm_object_t -vmm_mem_alloc(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) -{ - int error; - vm_object_t obj; - - if (gpa & PAGE_MASK) - panic("vmm_mem_alloc: invalid gpa %#lx", gpa); - - if (len == 0 || (len & PAGE_MASK) != 0) - panic("vmm_mem_alloc: invalid allocation size %lu", len); - - obj = vm_object_allocate(OBJT_DEFAULT, len >> PAGE_SHIFT); - if (obj != NULL) { - error = vm_map_find(&vmspace->vm_map, obj, 0, &gpa, len, 0, - VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); - if (error != KERN_SUCCESS) { - vm_object_deallocate(obj); - obj = NULL; - } - } - - return (obj); -} - -void -vmm_mem_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) -{ - - vm_map_remove(&vmspace->vm_map, gpa, gpa + len); -} - vm_paddr_t vmm_mem_maxaddr(void) { diff --git a/sys/amd64/vmm/vmm_mem.h b/sys/amd64/vmm/vmm_mem.h index a375070..7773faa 100644 --- a/sys/amd64/vmm/vmm_mem.h +++ b/sys/amd64/vmm/vmm_mem.h @@ -33,10 +33,8 @@ struct vmspace; struct vm_object; int vmm_mem_init(void); -struct vm_object *vmm_mem_alloc(struct vmspace *, vm_paddr_t gpa, size_t size); struct vm_object *vmm_mmio_alloc(struct vmspace *, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); -void vmm_mem_free(struct vmspace *, vm_paddr_t gpa, size_t size); void vmm_mmio_free(struct vmspace *, vm_paddr_t gpa, size_t size); vm_paddr_t vmm_mem_maxaddr(void); diff --git a/sys/arm/arm/bcopyinout.S b/sys/arm/arm/bcopyinout.S index 8885717..c030e24 100644 --- a/sys/arm/arm/bcopyinout.S +++ b/sys/arm/arm/bcopyinout.S @@ -38,6 +38,7 @@ #include "assym.s" +#include <machine/acle-compat.h> #include <machine/asm.h> #include <sys/errno.h> @@ -54,7 +55,7 @@ __FBSDID("$FreeBSD$"); .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/bcopyinout_xscale.S b/sys/arm/arm/bcopyinout_xscale.S index ad61200..7a5abb5 100644 --- a/sys/arm/arm/bcopyinout_xscale.S +++ b/sys/arm/arm/bcopyinout_xscale.S @@ -38,11 +38,13 @@ #include <machine/asm.h> __FBSDID("$FreeBSD$"); +#include <machine/acle-compat.h> + .syntax unified .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/copystr.S b/sys/arm/arm/copystr.S index d41525a..48c296b 100644 --- a/sys/arm/arm/copystr.S +++ b/sys/arm/arm/copystr.S @@ -39,6 +39,7 @@ */ #include "assym.s" +#include <machine/acle-compat.h> #include <machine/asm.h> #include <machine/armreg.h> __FBSDID("$FreeBSD$"); @@ -48,7 +49,7 @@ __FBSDID("$FreeBSD$"); .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index 56db9ca..636ba75 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -34,6 +34,9 @@ * Cortex-A7, Cortex-A15, ARMv8 and later Generic Timer */ +#include "opt_acpi.h" +#include "opt_platform.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -51,12 +54,17 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/intr.h> +#ifdef FDT #include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#endif -#include <machine/bus.h> +#ifdef DEV_ACPI +#include <contrib/dev/acpica/include/acpi.h> +#include <dev/acpica/acpivar.h> +#endif #define GT_CTRL_ENABLE (1 << 0) #define GT_CTRL_INT_MASK (1 << 1) @@ -247,8 +255,9 @@ arm_tmr_intr(void *arg) return (FILTER_HANDLED); } +#ifdef FDT static int -arm_tmr_probe(device_t dev) +arm_tmr_fdt_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) @@ -264,14 +273,62 @@ arm_tmr_probe(device_t dev) return (ENXIO); } +#endif + +#ifdef DEV_ACPI +static void +arm_tmr_acpi_identify(driver_t *driver, device_t parent) +{ + ACPI_TABLE_GTDT *gtdt; + vm_paddr_t physaddr; + device_t dev; + + physaddr = acpi_find_table(ACPI_SIG_GTDT); + if (physaddr == 0) + return; + + gtdt = acpi_map_table(physaddr, ACPI_SIG_GTDT); + if (gtdt == NULL) { + device_printf(parent, "gic: Unable to map the GTDT\n"); + return; + } + + dev = BUS_ADD_CHILD(parent, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE, + "generic_timer", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0, + gtdt->SecureEl1Interrupt, 1); + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1, + gtdt->NonSecureEl1Interrupt, 1); + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2, + gtdt->VirtualTimerInterrupt, 1); + +out: + acpi_unmap_table(gtdt); +} + +static int +arm_tmr_acpi_probe(device_t dev) +{ + + device_set_desc(dev, "ARM Generic Timer"); + return (BUS_PROBE_NOWILDCARD); +} +#endif static int arm_tmr_attach(device_t dev) { struct arm_tmr_softc *sc; +#ifdef FDT phandle_t node; pcell_t clock; +#endif int error; int i; @@ -279,12 +336,17 @@ arm_tmr_attach(device_t dev) if (arm_tmr_sc) return (ENXIO); +#ifdef FDT /* Get the base clock frequency */ node = ofw_bus_get_node(dev); - error = OF_getprop(node, "clock-frequency", &clock, sizeof(clock)); - if (error > 0) { - sc->clkfreq = fdt32_to_cpu(clock); + if (node > 0) { + error = OF_getprop(node, "clock-frequency", &clock, + sizeof(clock)); + if (error > 0) { + sc->clkfreq = fdt32_to_cpu(clock); + } } +#endif if (sc->clkfreq == 0) { /* Try to get clock frequency from timer */ @@ -339,24 +401,46 @@ arm_tmr_attach(device_t dev) return (0); } -static device_method_t arm_tmr_methods[] = { - DEVMETHOD(device_probe, arm_tmr_probe), +#ifdef FDT +static device_method_t arm_tmr_fdt_methods[] = { + DEVMETHOD(device_probe, arm_tmr_fdt_probe), DEVMETHOD(device_attach, arm_tmr_attach), { 0, 0 } }; -static driver_t arm_tmr_driver = { +static driver_t arm_tmr_fdt_driver = { "generic_timer", - arm_tmr_methods, + arm_tmr_fdt_methods, sizeof(struct arm_tmr_softc), }; -static devclass_t arm_tmr_devclass; +static devclass_t arm_tmr_fdt_devclass; -EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0, - BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); -EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0, - BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +#endif + +#ifdef DEV_ACPI +static device_method_t arm_tmr_acpi_methods[] = { + DEVMETHOD(device_identify, arm_tmr_acpi_identify), + DEVMETHOD(device_probe, arm_tmr_acpi_probe), + DEVMETHOD(device_attach, arm_tmr_attach), + { 0, 0 } +}; + +static driver_t arm_tmr_acpi_driver = { + "generic_timer", + arm_tmr_acpi_methods, + sizeof(struct arm_tmr_softc), +}; + +static devclass_t arm_tmr_acpi_devclass; + +EARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +#endif void DELAY(int usec) diff --git a/sys/arm/arm/locore-v4.S b/sys/arm/arm/locore-v4.S index d798e97..cc4f636 100644 --- a/sys/arm/arm/locore-v4.S +++ b/sys/arm/arm/locore-v4.S @@ -49,8 +49,7 @@ __FBSDID("$FreeBSD$"); * * TODO: Fix the ARMv4/v5 case. */ -#if (defined(FLASHADDR) || defined(LOADERRAMADDR) || !defined(_ARM_ARCH_6)) && \ - !defined(PHYSADDR) +#ifndef PHYSADDR #error PHYSADDR must be defined for this configuration #endif diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index 7d5ba97..cddcdab 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -240,7 +240,7 @@ ASENTRY_NP(init_mmu) * - All is set to uncacheable memory */ ldr r0, =0xAAAAA - mrc CP15_PRRR(r0) + mcr CP15_PRRR(r0) mov r0, #0 mcr CP15_NMRR(r0) #endif diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 55b4cb9..99d4572 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -911,7 +911,7 @@ fake_preload_metadata(struct arm_boot_params *abp __unused) void pcpu0_init(void) { -#if ARM_ARCH_6 || ARM_ARCH_7A || defined(CPU_MV_PJ4B) +#if __ARM_ARCH >= 6 set_curthread(&thread0); #endif pcpu_init(pcpup, 0, sizeof(struct pcpu)); diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 833b42f..b15062c 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -395,8 +395,8 @@ abort_handler(struct trapframe *tf, int prefetch) p = td->td_proc; if (usermode) { td->td_pticks = 0; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); } /* Invoke the appropriate handler, if necessary. */ diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index 26e7bf6..52a5baa 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -78,10 +78,6 @@ * Created : 28/11/94 */ -#ifdef KDTRACE_HOOKS -#include <sys/dtrace_bsd.h> -#endif - #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -98,6 +94,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_map.h> #include <vm/vm_extern.h> +#include <machine/acle-compat.h> #include <machine/cpu.h> #include <machine/frame.h> #include <machine/machdep.h> @@ -108,6 +105,10 @@ __FBSDID("$FreeBSD$"); #include <sys/kdb.h> #endif +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> +#endif + extern char fusubailout[]; #ifdef DEBUG @@ -214,8 +215,8 @@ abort_handler(struct trapframe *tf, int type) if (user) { td->td_pticks = 0; td->td_frame = tf; - if (td->td_ucred != td->td_proc->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != td->td_proc->p_cowgen) + thread_cow_update(td); } /* Grab the current pcb */ @@ -325,7 +326,7 @@ abort_handler(struct trapframe *tf, int type) * location, so we can deal with those quickly. Otherwise we need to * disassemble the faulting instruction to determine if it was a write. */ -#if ARM_ARCH_6 || ARM_ARCH_7A +#if __ARM_ARCH >= 6 ftype = (fsr & FAULT_WNR) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ; #else if (IS_PERMISSION_FAULT(fsr)) @@ -644,8 +645,8 @@ prefetch_abort_handler(struct trapframe *tf) if (TRAP_USERMODE(tf)) { td->td_frame = tf; - if (td->td_ucred != td->td_proc->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != td->td_proc->p_cowgen) + thread_cow_update(td); } fault_pc = tf->tf_pc; if (td->td_md.md_spinlock_count == 0) { diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE index 38c6b4a..8b06d20 100644 --- a/sys/arm/conf/BEAGLEBONE +++ b/sys/arm/conf/BEAGLEBONE @@ -138,3 +138,11 @@ device fdt_pinctrl # Flattened Device Tree options FDT # Configure using FDT/DTB data + +# Comment following lines for boot console on serial port +device vt +device videomode +device hdmi +device ums +device ukbd +device kbdmux diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES index 85a4c16..885bfd1 100644 --- a/sys/arm/conf/NOTES +++ b/sys/arm/conf/NOTES @@ -86,3 +86,26 @@ nodevice cxgbe nodevice pcii nodevice snd_cmi nodevice tnt4882 + +# +# Enable the kernel DTrace hooks which are required to load the DTrace +# kernel modules. +# +options KDTRACE_HOOKS + +# DTrace core +# NOTE: introduces CDDL-licensed components into the kernel +#device dtrace + +# DTrace modules +#device dtrace_lockstat +#device dtrace_profile +#device dtrace_sdt +#device dtrace_fbt +#device dtrace_systrace +#device dtrace_prototype +#device dtnfscl +#device dtmalloc + +# Alternatively include all the DTrace modules +#device dtraceall diff --git a/sys/arm/include/pcpu.h b/sys/arm/include/pcpu.h index 4ce8b3a..73400c5 100644 --- a/sys/arm/include/pcpu.h +++ b/sys/arm/include/pcpu.h @@ -32,6 +32,7 @@ #ifdef _KERNEL +#include <machine/acle-compat.h> #include <machine/cpuconf.h> #define ALT_STACK_SIZE 128 @@ -40,7 +41,7 @@ struct vmspace; #endif /* _KERNEL */ -#ifdef VFP +#if __ARM_ARCH >= 6 #define PCPU_MD_FIELDS \ unsigned int pc_vfpsid; \ unsigned int pc_vfpmvfr0; \ @@ -58,9 +59,8 @@ struct pcb; struct pcpu; extern struct pcpu *pcpup; -#if ARM_ARCH_6 || ARM_ARCH_7A -/* or ARM_TP_ADDRESS mark REMOVE ME NOTE */ +#if __ARM_ARCH >= 6 #define CPU_MASK (0xf) #ifndef SMP diff --git a/sys/arm/ti/am335x/am335x_lcd.c b/sys/arm/ti/am335x/am335x_lcd.c index 501042a..1f38664 100644 --- a/sys/arm/ti/am335x/am335x_lcd.c +++ b/sys/arm/ti/am335x/am335x_lcd.c @@ -52,6 +52,10 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <arm/ti/am335x/hdmi.h> +#include <dev/videomode/videomode.h> +#include <dev/videomode/edidvar.h> + #include <dev/fb/fbreg.h> #ifdef DEV_SC #include <dev/syscons/syscons.h> @@ -66,6 +70,7 @@ __FBSDID("$FreeBSD$"); #include "am335x_pwm.h" #include "fb_if.h" +#include "hdmi_if.h" #define LCD_PID 0x00 #define LCD_CTRL 0x04 @@ -176,11 +181,20 @@ __FBSDID("$FreeBSD$"); #define LCD_WRITE4(_sc, reg, value) \ bus_write_4((_sc)->sc_mem_res, reg, value); - /* Backlight is controlled by eCAS interface on PWM unit 0 */ #define PWM_UNIT 0 #define PWM_PERIOD 100 +#define MODE_HBP(mode) ((mode)->htotal - (mode)->hsync_end) +#define MODE_HFP(mode) ((mode)->hsync_start - (mode)->hdisplay) +#define MODE_HSW(mode) ((mode)->hsync_end - (mode)->hsync_start) +#define MODE_VBP(mode) ((mode)->vtotal - (mode)->vsync_end) +#define MODE_VFP(mode) ((mode)->vsync_start - (mode)->vdisplay) +#define MODE_VSW(mode) ((mode)->vsync_end - (mode)->vsync_start) + +#define MAX_PIXEL_CLOCK 126000 +#define MAX_BANDWIDTH (1280*1024*60) + struct am335x_lcd_softc { device_t sc_dev; struct fb_info sc_fb_info; @@ -191,12 +205,18 @@ struct am335x_lcd_softc { int sc_backlight; struct sysctl_oid *sc_oid; + struct panel_info sc_panel; + /* Framebuffer */ bus_dma_tag_t sc_dma_tag; bus_dmamap_t sc_dma_map; size_t sc_fb_size; bus_addr_t sc_fb_phys; uint8_t *sc_fb_base; + + /* HDMI framer */ + phandle_t sc_hdmi_framer; + eventhandler_tag sc_hdmi_evh; }; static void @@ -214,13 +234,22 @@ am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) static uint32_t am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq) { - uint32_t div; + uint32_t div, i; + uint32_t delta, min_delta; + + min_delta = freq; + div = 255; + /* Raster mode case: divisors are in range from 2 to 255 */ - for (div = 2; div < 255; div++) - if (reference/div <= freq) - return (div); + for (i = 2; i < 255; i++) { + delta = abs(reference/i - freq); + if (delta < min_delta) { + div = i; + min_delta = delta; + } + } - return (255); + return (div); } static int @@ -229,7 +258,7 @@ am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS) struct am335x_lcd_softc *sc = (struct am335x_lcd_softc*)arg1; int error; int backlight; - + backlight = sc->sc_backlight; error = sysctl_handle_int(oidp, &backlight, 0, req); @@ -251,6 +280,81 @@ am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS) return (error); } +static uint32_t +am335x_mode_vrefresh(const struct videomode *mode) +{ + uint32_t refresh; + + /* Calculate vertical refresh rate */ + refresh = (mode->dot_clock * 1000 / mode->htotal); + refresh = (refresh + mode->vtotal / 2) / mode->vtotal; + + if (mode->flags & VID_INTERLACE) + refresh *= 2; + if (mode->flags & VID_DBLSCAN) + refresh /= 2; + + return refresh; +} + +static int +am335x_mode_is_valid(const struct videomode *mode) +{ + uint32_t hbp, hfp, hsw; + uint32_t vbp, vfp, vsw; + + if (mode->dot_clock > MAX_PIXEL_CLOCK) + return (0); + + if (mode->hdisplay & 0xf) + return (0); + + if (mode->vdisplay > 2048) + return (0); + + /* Check ranges for timing parameters */ + hbp = MODE_HBP(mode) - 1; + hfp = MODE_HFP(mode) - 1; + hsw = MODE_HSW(mode) - 1; + vbp = MODE_VBP(mode); + vfp = MODE_VFP(mode); + vsw = MODE_VSW(mode) - 1; + + if (hbp > 0x3ff) + return (0); + if (hfp > 0x3ff) + return (0); + if (hsw > 0x3ff) + return (0); + + if (vbp > 0xff) + return (0); + if (vfp > 0xff) + return (0); + if (vsw > 0x3f) + return (0); + if (mode->vdisplay*mode->hdisplay*am335x_mode_vrefresh(mode) + > MAX_BANDWIDTH) + return (0); + + return (1); +} + +static void +am335x_read_hdmi_property(device_t dev) +{ + phandle_t node; + phandle_t hdmi_xref; + struct am335x_lcd_softc *sc; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + if (OF_getencprop(node, "hdmi", &hdmi_xref, sizeof(hdmi_xref)) == -1) + sc->sc_hdmi_framer = 0; + else + sc->sc_hdmi_framer = hdmi_xref; +} + static int am335x_read_property(device_t dev, phandle_t node, const char *name, uint32_t *val) { @@ -343,44 +447,34 @@ out: static int am335x_read_panel_info(device_t dev, phandle_t node, struct panel_info *panel) { - int error; phandle_t panel_info_node; panel_info_node = ofw_bus_find_child(node, "panel-info"); if (panel_info_node == 0) return (-1); - error = 0; - - if ((error = am335x_read_property(dev, panel_info_node, - "ac-bias", &panel->ac_bias))) - goto out; + am335x_read_property(dev, panel_info_node, + "ac-bias", &panel->ac_bias); - if ((error = am335x_read_property(dev, panel_info_node, - "ac-bias-intrpt", &panel->ac_bias_intrpt))) - goto out; + am335x_read_property(dev, panel_info_node, + "ac-bias-intrpt", &panel->ac_bias_intrpt); - if ((error = am335x_read_property(dev, panel_info_node, - "dma-burst-sz", &panel->dma_burst_sz))) - goto out; + am335x_read_property(dev, panel_info_node, + "dma-burst-sz", &panel->dma_burst_sz); - if ((error = am335x_read_property(dev, panel_info_node, - "bpp", &panel->bpp))) - goto out; + am335x_read_property(dev, panel_info_node, + "bpp", &panel->bpp); - if ((error = am335x_read_property(dev, panel_info_node, - "fdd", &panel->fdd))) - goto out; + am335x_read_property(dev, panel_info_node, + "fdd", &panel->fdd); - if ((error = am335x_read_property(dev, panel_info_node, - "sync-edge", &panel->sync_edge))) - goto out; + am335x_read_property(dev, panel_info_node, + "sync-edge", &panel->sync_edge); - error = am335x_read_property(dev, panel_info_node, + am335x_read_property(dev, panel_info_node, "sync-ctrl", &panel->sync_ctrl); -out: - return (error); + return (0); } static void @@ -442,119 +536,75 @@ done: reg = LCD_READ4(sc, LCD_END_OF_INT_IND); } -static int -am335x_lcd_probe(device_t dev) +static const struct videomode * +am335x_lcd_pick_mode(struct edid_info *ei) { -#ifdef DEV_SC - int err; -#endif - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); + const struct videomode *videomode; + const struct videomode *m; + int n; - if (!ofw_bus_is_compatible(dev, "ti,am33xx-tilcdc")) - return (ENXIO); + /* Get standard VGA as default */ + videomode = NULL; - device_set_desc(dev, "AM335x LCD controller"); + /* + * Pick a mode. + */ + if (ei->edid_preferred_mode != NULL) { + if (am335x_mode_is_valid(ei->edid_preferred_mode)) + videomode = ei->edid_preferred_mode; + } -#ifdef DEV_SC - err = sc_probe_unit(device_get_unit(dev), - device_get_flags(dev) | SC_AUTODETECT_KBD); - if (err != 0) - return (err); -#endif + if (videomode == NULL) { + m = ei->edid_modes; + + sort_modes(ei->edid_modes, + &ei->edid_preferred_mode, + ei->edid_nmodes); + for (n = 0; n < ei->edid_nmodes; n++) + if (am335x_mode_is_valid(&m[n])) { + videomode = &m[n]; + break; + } + } - return (BUS_PROBE_DEFAULT); + return videomode; } static int -am335x_lcd_attach(device_t dev) +am335x_lcd_configure(struct am335x_lcd_softc *sc) { - struct am335x_lcd_softc *sc; - int rid; int div; - struct panel_info panel; uint32_t reg, timing0, timing1, timing2; - struct sysctl_ctx_list *ctx; - struct sysctl_oid *tree; uint32_t burst_log; - int err; size_t dma_size; uint32_t hbp, hfp, hsw; uint32_t vbp, vfp, vsw; uint32_t width, height; - phandle_t root, panel_node; - - sc = device_get_softc(dev); - sc->sc_dev = dev; - - root = OF_finddevice("/"); - if (root == 0) { - device_printf(dev, "failed to get FDT root node\n"); - return (ENXIO); - } - - panel_node = fdt_find_compatible(root, "ti,tilcdc,panel", 1); - if (panel_node == 0) { - device_printf(dev, "failed to find compatible panel in FDT blob\n"); - return (ENXIO); - } - - if (am335x_read_panel_info(dev, panel_node, &panel)) { - device_printf(dev, "failed to read panel info\n"); - return (ENXIO); - } + unsigned int ref_freq; + int err; - if (am335x_read_timing(dev, panel_node, &panel)) { - device_printf(dev, "failed to read timings\n"); + /* + * try to adjust clock to get double of requested frequency + * HDMI/DVI displays are very sensitive to error in frequncy value + */ + if (ti_prcm_clk_set_source_freq(LCDC_CLK, sc->sc_panel.panel_pxl_clk*2)) { + device_printf(sc->sc_dev, "can't set source frequency\n"); return (ENXIO); } - int ref_freq = 0; - ti_prcm_clk_enable(LCDC_CLK); if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) { - device_printf(dev, "Can't get reference frequency\n"); + device_printf(sc->sc_dev, "can't get reference frequency\n"); return (ENXIO); } - rid = 0; - sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->sc_mem_res) { - device_printf(dev, "cannot allocate memory window\n"); - return (ENXIO); - } - - rid = 0; - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - if (!sc->sc_irq_res) { - bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); - device_printf(dev, "cannot allocate interrupt\n"); - return (ENXIO); - } - - if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, - NULL, am335x_lcd_intr, sc, - &sc->sc_intr_hl) != 0) { - bus_release_resource(dev, SYS_RES_IRQ, rid, - sc->sc_irq_res); - bus_release_resource(dev, SYS_RES_MEMORY, rid, - sc->sc_mem_res); - device_printf(dev, "Unable to setup the irq handler.\n"); - return (ENXIO); - } - - LCD_LOCK_INIT(sc); - /* Panle initialization */ - dma_size = round_page(panel.panel_width*panel.panel_height*panel.bpp/8); + dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8); /* * Now allocate framebuffer memory */ err = bus_dma_tag_create( - bus_get_dma_tag(dev), + bus_get_dma_tag(sc->sc_dev), 4, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ @@ -564,49 +614,49 @@ am335x_lcd_attach(device_t dev) NULL, NULL, /* lockfunc, lockarg */ &sc->sc_dma_tag); if (err) - goto fail; + goto done; err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base, BUS_DMA_COHERENT, &sc->sc_dma_map); if (err) { - device_printf(dev, "cannot allocate framebuffer\n"); - goto fail; + device_printf(sc->sc_dev, "cannot allocate framebuffer\n"); + goto done; } err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base, dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT); if (err) { - device_printf(dev, "cannot load DMA map\n"); - goto fail; + device_printf(sc->sc_dev, "cannot load DMA map\n"); + goto done; } /* Make sure it's blank */ - memset(sc->sc_fb_base, 0x00, dma_size); + memset(sc->sc_fb_base, 0x0, dma_size); /* Calculate actual FB Size */ - sc->sc_fb_size = panel.panel_width*panel.panel_height*panel.bpp/8; + sc->sc_fb_size = sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8; /* Only raster mode is supported */ reg = CTRL_RASTER_MODE; - div = am335x_lcd_calc_divisor(ref_freq, panel.panel_pxl_clk); + div = am335x_lcd_calc_divisor(ref_freq, sc->sc_panel.panel_pxl_clk); reg |= (div << CTRL_DIV_SHIFT); LCD_WRITE4(sc, LCD_CTRL, reg); /* Set timing */ timing0 = timing1 = timing2 = 0; - hbp = panel.panel_hbp - 1; - hfp = panel.panel_hfp - 1; - hsw = panel.panel_hsw - 1; + hbp = sc->sc_panel.panel_hbp - 1; + hfp = sc->sc_panel.panel_hfp - 1; + hsw = sc->sc_panel.panel_hsw - 1; - vbp = panel.panel_vbp; - vfp = panel.panel_vfp; - vsw = panel.panel_vsw - 1; + vbp = sc->sc_panel.panel_vbp; + vfp = sc->sc_panel.panel_vfp; + vsw = sc->sc_panel.panel_vsw - 1; - height = panel.panel_height - 1; - width = panel.panel_width - 1; + height = sc->sc_panel.panel_height - 1; + width = sc->sc_panel.panel_width - 1; /* Horizontal back porch */ timing0 |= (hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT; @@ -636,22 +686,22 @@ am335x_lcd_attach(device_t dev) << RASTER_TIMING_2_LPP_B10_SHIFT; /* clock signal settings */ - if (panel.sync_ctrl) + if (sc->sc_panel.sync_ctrl) timing2 |= RASTER_TIMING_2_PHSVS; - if (panel.sync_edge) + if (sc->sc_panel.sync_edge) timing2 |= RASTER_TIMING_2_PHSVS_RISE; else timing2 |= RASTER_TIMING_2_PHSVS_FALL; - if (panel.hsync_active == 0) + if (sc->sc_panel.hsync_active == 0) timing2 |= RASTER_TIMING_2_IHS; - if (panel.vsync_active == 0) + if (sc->sc_panel.vsync_active == 0) timing2 |= RASTER_TIMING_2_IVS; - if (panel.pixelclk_active == 0) + if (sc->sc_panel.pixelclk_active == 0) timing2 |= RASTER_TIMING_2_IPC; /* AC bias */ - timing2 |= (panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT); - timing2 |= (panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT); + timing2 |= (sc->sc_panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT); + timing2 |= (sc->sc_panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT); LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0); LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1); @@ -660,7 +710,7 @@ am335x_lcd_attach(device_t dev) /* DMA settings */ reg = LCDDMA_CTRL_FB0_FB1; /* Find power of 2 for current burst size */ - switch (panel.dma_burst_sz) { + switch (sc->sc_panel.dma_burst_sz) { case 1: burst_log = 0; break; @@ -690,11 +740,11 @@ am335x_lcd_attach(device_t dev) /* Enable LCD */ reg = RASTER_CTRL_LCDTFT; - reg |= (panel.fdd << RASTER_CTRL_REQDLY_SHIFT); + reg |= (sc->sc_panel.fdd << RASTER_CTRL_REQDLY_SHIFT); reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT); - if (panel.bpp >= 24) + if (sc->sc_panel.bpp >= 24) reg |= RASTER_CTRL_TFT24; - if (panel.bpp == 32) + if (sc->sc_panel.bpp == 32) reg |= RASTER_CTRL_TFT24_UNPACKED; LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); @@ -717,54 +767,241 @@ am335x_lcd_attach(device_t dev) LCD_WRITE4(sc, LCD_SYSCONFIG, SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART); - /* Init backlight interface */ - ctx = device_get_sysctl_ctx(sc->sc_dev); - tree = device_get_sysctl_tree(sc->sc_dev); - sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0, - am335x_lcd_sysctl_backlight, "I", "LCD backlight"); - sc->sc_backlight = 0; - /* Check if eCAS interface is available at this point */ - if (am335x_pwm_config_ecap(PWM_UNIT, - PWM_PERIOD, PWM_PERIOD) == 0) - sc->sc_backlight = 100; - sc->sc_fb_info.fb_name = device_get_nameunit(sc->sc_dev); sc->sc_fb_info.fb_vbase = (intptr_t)sc->sc_fb_base; sc->sc_fb_info.fb_pbase = sc->sc_fb_phys; sc->sc_fb_info.fb_size = sc->sc_fb_size; - sc->sc_fb_info.fb_bpp = sc->sc_fb_info.fb_depth = panel.bpp; - sc->sc_fb_info.fb_stride = panel.panel_width*panel.bpp / 8; - sc->sc_fb_info.fb_width = panel.panel_width; - sc->sc_fb_info.fb_height = panel.panel_height; + sc->sc_fb_info.fb_bpp = sc->sc_fb_info.fb_depth = sc->sc_panel.bpp; + sc->sc_fb_info.fb_stride = sc->sc_panel.panel_width*sc->sc_panel.bpp / 8; + sc->sc_fb_info.fb_width = sc->sc_panel.panel_width; + sc->sc_fb_info.fb_height = sc->sc_panel.panel_height; #ifdef DEV_SC - err = (sc_attach_unit(device_get_unit(dev), - device_get_flags(dev) | SC_AUTODETECT_KBD)); + err = (sc_attach_unit(device_get_unit(sc->sc_dev), + device_get_flags(sc->sc_dev) | SC_AUTODETECT_KBD)); if (err) { - device_printf(dev, "failed to attach syscons\n"); + device_printf(sc->sc_dev, "failed to attach syscons\n"); goto fail; } am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel); #else /* VT */ - device_t fbd = device_add_child(dev, "fbd", - device_get_unit(dev)); - if (fbd == NULL) { - device_printf(dev, "Failed to add fbd child\n"); - goto fail; + device_t fbd = device_add_child(sc->sc_dev, "fbd", + device_get_unit(sc->sc_dev)); + if (fbd != NULL) { + if (device_probe_and_attach(fbd) != 0) + device_printf(sc->sc_dev, "failed to attach fbd device\n"); + } else + device_printf(sc->sc_dev, "failed to add fbd child\n"); +#endif + +done: + return (err); +} + +static void +am335x_lcd_hdmi_event(void *arg) +{ + struct am335x_lcd_softc *sc; + const struct videomode *videomode; + struct videomode hdmi_mode; + device_t hdmi_dev; + uint8_t *edid; + uint32_t edid_len; + struct edid_info ei; + + sc = arg; + + /* Nothing to work with */ + if (!sc->sc_hdmi_framer) { + device_printf(sc->sc_dev, "HDMI event without HDMI framer set\n"); + return; } - if (device_probe_and_attach(fbd) != 0) { - device_printf(dev, "Failed to attach fbd device\n"); - goto fail; + + hdmi_dev = OF_device_from_xref(sc->sc_hdmi_framer); + if (!hdmi_dev) { + device_printf(sc->sc_dev, "no actual device for \"hdmi\" property\n"); + return; } + + edid = NULL; + edid_len = 0; + if (HDMI_GET_EDID(hdmi_dev, &edid, &edid_len) != 0) { + device_printf(sc->sc_dev, "failed to get EDID info from HDMI framer\n"); + return; + } + + videomode = NULL; + + if (edid_parse(edid, &ei) == 0) { + edid_print(&ei); + videomode = am335x_lcd_pick_mode(&ei); + } else + device_printf(sc->sc_dev, "failed to parse EDID\n"); + + /* Use standard VGA as fallback */ + if (videomode == NULL) + videomode = pick_mode_by_ref(640, 480, 60); + + if (videomode == NULL) { + device_printf(sc->sc_dev, "failed to find usable videomode"); + return; + } + + device_printf(sc->sc_dev, "detected videomode: %dx%d @ %dKHz\n", videomode->hdisplay, + videomode->vdisplay, am335x_mode_vrefresh(videomode)); + + sc->sc_panel.panel_width = videomode->hdisplay; + sc->sc_panel.panel_height = videomode->vdisplay; + sc->sc_panel.panel_hfp = videomode->hsync_start - videomode->hdisplay; + sc->sc_panel.panel_hbp = videomode->htotal - videomode->hsync_end; + sc->sc_panel.panel_hsw = videomode->hsync_end - videomode->hsync_start; + sc->sc_panel.panel_vfp = videomode->vsync_start - videomode->vdisplay; + sc->sc_panel.panel_vbp = videomode->vtotal - videomode->vsync_end; + sc->sc_panel.panel_vsw = videomode->vsync_end - videomode->vsync_start; + sc->sc_panel.pixelclk_active = 1; + + /* logic for HSYNC should be reversed */ + if (videomode->flags & VID_NHSYNC) + sc->sc_panel.hsync_active = 1; + else + sc->sc_panel.hsync_active = 0; + + if (videomode->flags & VID_NVSYNC) + sc->sc_panel.vsync_active = 0; + else + sc->sc_panel.vsync_active = 1; + + sc->sc_panel.panel_pxl_clk = videomode->dot_clock * 1000; + + am335x_lcd_configure(sc); + + memcpy(&hdmi_mode, videomode, sizeof(hdmi_mode)); + hdmi_mode.hskew = videomode->hsync_end - videomode->hsync_start; + hdmi_mode.flags |= VID_HSKEW; + + HDMI_SET_VIDEOMODE(hdmi_dev, &hdmi_mode); +} + +static int +am335x_lcd_probe(device_t dev) +{ +#ifdef DEV_SC + int err; #endif - return (0); + if (!ofw_bus_status_okay(dev)) + return (ENXIO); -fail: - return (err); + if (!ofw_bus_is_compatible(dev, "ti,am33xx-tilcdc")) + return (ENXIO); + + device_set_desc(dev, "AM335x LCD controller"); + +#ifdef DEV_SC + err = sc_probe_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD); + if (err != 0) + return (err); +#endif + + return (BUS_PROBE_DEFAULT); +} + +static int +am335x_lcd_attach(device_t dev) +{ + struct am335x_lcd_softc *sc; + + int err; + int rid; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree; + phandle_t root, panel_node; + + err = 0; + sc = device_get_softc(dev); + sc->sc_dev = dev; + + am335x_read_hdmi_property(dev); + + root = OF_finddevice("/"); + if (root == 0) { + device_printf(dev, "failed to get FDT root node\n"); + return (ENXIO); + } + + sc->sc_panel.ac_bias = 255; + sc->sc_panel.ac_bias_intrpt = 0; + sc->sc_panel.dma_burst_sz = 16; + sc->sc_panel.bpp = 16; + sc->sc_panel.fdd = 128; + sc->sc_panel.sync_edge = 0; + sc->sc_panel.sync_ctrl = 1; + + panel_node = fdt_find_compatible(root, "ti,tilcdc,panel", 1); + if (panel_node != 0) { + device_printf(dev, "using static panel info\n"); + if (am335x_read_panel_info(dev, panel_node, &sc->sc_panel)) { + device_printf(dev, "failed to read panel info\n"); + return (ENXIO); + } + + if (am335x_read_timing(dev, panel_node, &sc->sc_panel)) { + device_printf(dev, "failed to read timings\n"); + return (ENXIO); + } + } + + ti_prcm_clk_enable(LCDC_CLK); + + rid = 0; + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (!sc->sc_mem_res) { + device_printf(dev, "cannot allocate memory window\n"); + return (ENXIO); + } + + rid = 0; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (!sc->sc_irq_res) { + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); + device_printf(dev, "cannot allocate interrupt\n"); + return (ENXIO); + } + + if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, am335x_lcd_intr, sc, + &sc->sc_intr_hl) != 0) { + bus_release_resource(dev, SYS_RES_IRQ, rid, + sc->sc_irq_res); + bus_release_resource(dev, SYS_RES_MEMORY, rid, + sc->sc_mem_res); + device_printf(dev, "Unable to setup the irq handler.\n"); + return (ENXIO); + } + + LCD_LOCK_INIT(sc); + + /* Init backlight interface */ + ctx = device_get_sysctl_ctx(sc->sc_dev); + tree = device_get_sysctl_tree(sc->sc_dev); + sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + am335x_lcd_sysctl_backlight, "I", "LCD backlight"); + sc->sc_backlight = 0; + /* Check if eCAS interface is available at this point */ + if (am335x_pwm_config_ecap(PWM_UNIT, + PWM_PERIOD, PWM_PERIOD) == 0) + sc->sc_backlight = 100; + + sc->sc_hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event, + am335x_lcd_hdmi_event, sc, 0); + + return (0); } static int diff --git a/sys/arm/ti/am335x/am335x_lcd.h b/sys/arm/ti/am335x/am335x_lcd.h index e3c82db..ed0779f 100644 --- a/sys/arm/ti/am335x/am335x_lcd.h +++ b/sys/arm/ti/am335x/am335x_lcd.h @@ -29,6 +29,7 @@ #define __AM335X_LCD_H__ struct panel_info { + /* Timing part */ uint32_t panel_width; uint32_t panel_height; uint32_t panel_hfp; @@ -37,16 +38,17 @@ struct panel_info { uint32_t panel_vfp; uint32_t panel_vbp; uint32_t panel_vsw; + uint32_t hsync_active; + uint32_t vsync_active; + uint32_t panel_pxl_clk; + uint32_t ac_bias; uint32_t ac_bias_intrpt; uint32_t dma_burst_sz; uint32_t bpp; uint32_t fdd; - uint32_t hsync_active; - uint32_t vsync_active; uint32_t sync_edge; uint32_t sync_ctrl; - uint32_t panel_pxl_clk; uint32_t pixelclk_active; }; diff --git a/sys/arm/ti/am335x/am335x_pmic.c b/sys/arm/ti/am335x/am335x_pmic.c index 06d4a1a..eefece8 100644 --- a/sys/arm/ti/am335x/am335x_pmic.c +++ b/sys/arm/ti/am335x/am335x_pmic.c @@ -131,7 +131,7 @@ am335x_pmic_intr(void *arg) shutdown_nice(RB_POWEROFF); if (int_reg.aci) { snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", - status_reg.acpwr ? 1 : 0); + status_reg.acpwr); devctl_notify_f("ACPI", "ACAD", "power", notify_buf, M_NOWAIT); } } diff --git a/sys/arm/ti/am335x/am335x_prcm.c b/sys/arm/ti/am335x/am335x_prcm.c index fa47f63..69fa6e2 100644 --- a/sys/arm/ti/am335x/am335x_prcm.c +++ b/sys/arm/ti/am335x/am335x_prcm.c @@ -151,6 +151,7 @@ static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsign static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq); +static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq); static void am335x_prcm_reset(void); static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev); static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev); @@ -163,7 +164,8 @@ static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); .clk_deactivate = am335x_clk_noop_deactivate, \ .clk_set_source = am335x_clk_noop_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_GENERIC_CLOCK_DEV(i) \ @@ -172,7 +174,8 @@ static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_GPIO_CLOCK_DEV(i) \ @@ -181,7 +184,8 @@ static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_MMCHS_CLOCK_DEV(i) \ @@ -190,7 +194,8 @@ static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \ + .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \ + .clk_set_source_freq = NULL \ } struct ti_clock_dev ti_am335x_clk_devmap[] = { @@ -201,6 +206,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_sysclk_freq, + .clk_set_source_freq = NULL, }, /* MPU (ARM) core clocks */ { .id = MPU_CLK, @@ -209,6 +215,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_arm_fclk_freq, + .clk_set_source_freq = NULL, }, /* CPSW Ethernet Switch core clocks */ { .id = CPSW_CLK, @@ -217,6 +224,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* Mentor USB HS controller core clocks */ @@ -226,6 +234,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* LCD controller clocks */ @@ -235,6 +244,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_arm_disp_freq, + .clk_set_source_freq = am335x_clk_set_arm_disp_freq, }, /* UART */ @@ -296,6 +306,7 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* RTC */ @@ -627,6 +638,8 @@ am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) #define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) #define DPLL_DIV(reg) ((reg & 0x7f)+1) #define DPLL_MULT(reg) ((reg>>8) & 0x7FF) +#define DPLL_MAX_MUL 0x800 +#define DPLL_MAX_DIV 0x80 static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) @@ -662,6 +675,52 @@ am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq) return(0); } +static int +am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq) +{ + uint32_t sysclk; + uint32_t mul, div; + uint32_t i, j; + unsigned int delta, min_delta; + + am335x_clk_get_sysclk_freq(NULL, &sysclk); + + /* Bypass mode */ + prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); + + /* Make sure it's in bypass mode */ + while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) + & (1 << 8))) + DELAY(10); + + /* Dumb and non-optimal implementation */ + min_delta = freq; + for (i = 1; i < DPLL_MAX_MUL; i++) { + for (j = 1; j < DPLL_MAX_DIV; j++) { + delta = abs(freq - i*(sysclk/j)); + if (delta < min_delta) { + mul = i; + div = j; + min_delta = delta; + } + if (min_delta == 0) + break; + } + } + + prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1)); + + /* Locked mode */ + prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); + + int timeout = 10000; + while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) + & (1 << 0))) && timeout--) + DELAY(10); + + return(0); +} + static void am335x_prcm_reset(void) { @@ -724,27 +783,10 @@ am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev) if (sc == NULL) return (ENXIO); - /* Bypass mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); - - /* Make sure it's in bypass mode */ - while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 8))) - DELAY(10); - /* - * For now set frequency to 99*SYSFREQ/8 which is twice as - * HDMI 1080p pixel clock (minimum LCDC freq divisor is 2) + * For now set frequency to 2*VGA_PIXEL_CLOCK */ - prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (99 << 8) | 8); - - /* Locked mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); - - int timeout = 10000; - while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 0))) && timeout--) - DELAY(10); + am335x_clk_set_arm_disp_freq(clkdev, 25175000*2); /*set MODULEMODE to ENABLE(2) */ prcm_write_4(CM_PER_LCDC_CLKCTRL, 2); diff --git a/sys/arm/ti/am335x/files.am335x b/sys/arm/ti/am335x/files.am335x index 277ee52..7293fd0 100644 --- a/sys/arm/ti/am335x/files.am335x +++ b/sys/arm/ti/am335x/files.am335x @@ -16,5 +16,8 @@ arm/ti/am335x/am335x_scm_padconf.c standard arm/ti/am335x/am335x_usbss.c optional musb fdt arm/ti/am335x/am335x_musb.c optional musb fdt +arm/ti/am335x/hdmi_if.m optional hdmi +arm/ti/am335x/tda19988.c optional hdmi + arm/ti/ti_edma3.c standard arm/ti/cpsw/if_cpsw.c optional cpsw diff --git a/sys/arm/ti/am335x/hdmi.h b/sys/arm/ti/am335x/hdmi.h new file mode 100644 index 0000000..989d132 --- /dev/null +++ b/sys/arm/ti/am335x/hdmi.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2015 Oleksandr Tymoshenko + * 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 _HDMI_H_ +#define _HDMI_H_ + +#include <sys/eventhandler.h> + +typedef void (*hdmi_event_hook)(void *, int); +EVENTHANDLER_DECLARE(hdmi_event, hdmi_event_hook); + +#endif /* !_HDMI_H_ */ + diff --git a/sys/arm/ti/am335x/hdmi_if.m b/sys/arm/ti/am335x/hdmi_if.m new file mode 100644 index 0000000..e5c6080 --- /dev/null +++ b/sys/arm/ti/am335x/hdmi_if.m @@ -0,0 +1,50 @@ +#- +# Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@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 <sys/bus.h> +#include <dev/videomode/videomode.h> +#include <dev/videomode/edidvar.h> + +INTERFACE hdmi; + +# +# Get EDID info +# +METHOD int get_edid { + device_t dev; + uint8_t **edid; + uint32_t *edid_length; +}; + +# +# Set videomode +# +METHOD int set_videomode { + device_t dev; + const struct videomode *videomode; +}; diff --git a/sys/arm/ti/am335x/tda19988.c b/sys/arm/ti/am335x/tda19988.c new file mode 100644 index 0000000..83dcf43 --- /dev/null +++ b/sys/arm/ti/am335x/tda19988.c @@ -0,0 +1,810 @@ +/*- + * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +/* +* NXP TDA19988 HDMI encoder +*/ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/clock.h> +#include <sys/time.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/types.h> +#include <sys/systm.h> + +#include <dev/iicbus/iicbus.h> +#include <dev/iicbus/iiconf.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/videomode/videomode.h> +#include <dev/videomode/edidvar.h> +#include <arm/ti/am335x/hdmi.h> + +#include "iicbus_if.h" +#include "hdmi_if.h" + +#define MKREG(page, addr) (((page) << 8) | (addr)) + +#define REGPAGE(reg) (((reg) >> 8) & 0xff) +#define REGADDR(reg) ((reg) & 0xff) + +#define TDA_VERSION MKREG(0x00, 0x00) +#define TDA_MAIN_CNTRL0 MKREG(0x00, 0x01) +#define MAIN_CNTRL0_SR (1 << 0) +#define TDA_VERSION_MSB MKREG(0x00, 0x02) +#define TDA_SOFTRESET MKREG(0x00, 0x0a) +#define SOFTRESET_I2C (1 << 1) +#define SOFTRESET_AUDIO (1 << 0) +#define TDA_DDC_CTRL MKREG(0x00, 0x0b) +#define DDC_ENABLE 0 +#define TDA_CCLK MKREG(0x00, 0x0c) +#define CCLK_ENABLE 1 +#define TDA_INT_FLAGS_2 MKREG(0x00, 0x11) +#define INT_FLAGS_2_EDID_BLK_RD (1 << 1) + +#define TDA_VIP_CNTRL_0 MKREG(0x00, 0x20) +#define TDA_VIP_CNTRL_1 MKREG(0x00, 0x21) +#define TDA_VIP_CNTRL_2 MKREG(0x00, 0x22) +#define TDA_VIP_CNTRL_3 MKREG(0x00, 0x23) +#define VIP_CNTRL_3_SYNC_HS (2 << 4) +#define VIP_CNTRL_3_V_TGL (1 << 2) +#define VIP_CNTRL_3_H_TGL (1 << 1) + +#define TDA_VIP_CNTRL_4 MKREG(0x00, 0x24) +#define VIP_CNTRL_4_BLANKIT_NDE (0 << 2) +#define VIP_CNTRL_4_BLANKIT_HS_VS (1 << 2) +#define VIP_CNTRL_4_BLANKIT_NHS_VS (2 << 2) +#define VIP_CNTRL_4_BLANKIT_HE_VE (3 << 2) +#define VIP_CNTRL_4_BLC_NONE (0 << 0) +#define VIP_CNTRL_4_BLC_RGB444 (1 << 0) +#define VIP_CNTRL_4_BLC_YUV444 (2 << 0) +#define VIP_CNTRL_4_BLC_YUV422 (3 << 0) +#define TDA_VIP_CNTRL_5 MKREG(0x00, 0x25) +#define VIP_CNTRL_5_SP_CNT(n) (((n) & 3) << 1) +#define TDA_MUX_VP_VIP_OUT MKREG(0x00, 0x27) +#define TDA_MAT_CONTRL MKREG(0x00, 0x80) +#define MAT_CONTRL_MAT_BP (1 << 2) +#define TDA_VIDFORMAT MKREG(0x00, 0xa0) +#define TDA_REFPIX_MSB MKREG(0x00, 0xa1) +#define TDA_REFPIX_LSB MKREG(0x00, 0xa2) +#define TDA_REFLINE_MSB MKREG(0x00, 0xa3) +#define TDA_REFLINE_LSB MKREG(0x00, 0xa4) +#define TDA_NPIX_MSB MKREG(0x00, 0xa5) +#define TDA_NPIX_LSB MKREG(0x00, 0xa6) +#define TDA_NLINE_MSB MKREG(0x00, 0xa7) +#define TDA_NLINE_LSB MKREG(0x00, 0xa8) +#define TDA_VS_LINE_STRT_1_MSB MKREG(0x00, 0xa9) +#define TDA_VS_LINE_STRT_1_LSB MKREG(0x00, 0xaa) +#define TDA_VS_PIX_STRT_1_MSB MKREG(0x00, 0xab) +#define TDA_VS_PIX_STRT_1_LSB MKREG(0x00, 0xac) +#define TDA_VS_LINE_END_1_MSB MKREG(0x00, 0xad) +#define TDA_VS_LINE_END_1_LSB MKREG(0x00, 0xae) +#define TDA_VS_PIX_END_1_MSB MKREG(0x00, 0xaf) +#define TDA_VS_PIX_END_1_LSB MKREG(0x00, 0xb0) +#define TDA_VS_LINE_STRT_2_MSB MKREG(0x00, 0xb1) +#define TDA_VS_LINE_STRT_2_LSB MKREG(0x00, 0xb2) +#define TDA_VS_PIX_STRT_2_MSB MKREG(0x00, 0xb3) +#define TDA_VS_PIX_STRT_2_LSB MKREG(0x00, 0xb4) +#define TDA_VS_LINE_END_2_MSB MKREG(0x00, 0xb5) +#define TDA_VS_LINE_END_2_LSB MKREG(0x00, 0xb6) +#define TDA_VS_PIX_END_2_MSB MKREG(0x00, 0xb7) +#define TDA_VS_PIX_END_2_LSB MKREG(0x00, 0xb8) +#define TDA_HS_PIX_START_MSB MKREG(0x00, 0xb9) +#define TDA_HS_PIX_START_LSB MKREG(0x00, 0xba) +#define TDA_HS_PIX_STOP_MSB MKREG(0x00, 0xbb) +#define TDA_HS_PIX_STOP_LSB MKREG(0x00, 0xbc) +#define TDA_VWIN_START_1_MSB MKREG(0x00, 0xbd) +#define TDA_VWIN_START_1_LSB MKREG(0x00, 0xbe) +#define TDA_VWIN_END_1_MSB MKREG(0x00, 0xbf) +#define TDA_VWIN_END_1_LSB MKREG(0x00, 0xc0) +#define TDA_VWIN_START_2_MSB MKREG(0x00, 0xc1) +#define TDA_VWIN_START_2_LSB MKREG(0x00, 0xc2) +#define TDA_VWIN_END_2_MSB MKREG(0x00, 0xc3) +#define TDA_VWIN_END_2_LSB MKREG(0x00, 0xc4) +#define TDA_DE_START_MSB MKREG(0x00, 0xc5) +#define TDA_DE_START_LSB MKREG(0x00, 0xc6) +#define TDA_DE_STOP_MSB MKREG(0x00, 0xc7) +#define TDA_DE_STOP_LSB MKREG(0x00, 0xc8) + +#define TDA_TBG_CNTRL_0 MKREG(0x00, 0xca) +#define TBG_CNTRL_0_SYNC_ONCE (1 << 7) +#define TBG_CNTRL_0_SYNC_MTHD (1 << 6) + +#define TDA_TBG_CNTRL_1 MKREG(0x00, 0xcb) +#define TBG_CNTRL_1_DWIN_DIS (1 << 6) +#define TBG_CNTRL_1_TGL_EN (1 << 2) +#define TBG_CNTRL_1_V_TGL (1 << 1) +#define TBG_CNTRL_1_H_TGL (1 << 0) + +#define TDA_HVF_CNTRL_0 MKREG(0x00, 0xe4) +#define HVF_CNTRL_0_PREFIL_NONE (0 << 2) +#define HVF_CNTRL_0_INTPOL_BYPASS (0 << 0) +#define TDA_HVF_CNTRL_1 MKREG(0x00, 0xe5) +#define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) +#define HVF_CNTRL_1_VQR_FULL HVF_CNTRL_1_VQR(0) +#define TDA_ENABLE_SPACE MKREG(0x00, 0xd6) +#define TDA_RPT_CNTRL MKREG(0x00, 0xf0) + +#define TDA_PLL_SERIAL_1 MKREG(0x02, 0x00) +#define PLL_SERIAL_1_SRL_MAN_IP (1 << 6) +#define TDA_PLL_SERIAL_2 MKREG(0x02, 0x01) +#define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) +#define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 0x3) << 0) +#define TDA_PLL_SERIAL_3 MKREG(0x02, 0x02) +#define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) +#define PLL_SERIAL_3_SRL_DE (1 << 2) +#define PLL_SERIAL_3_SRL_CCIR (1 << 0) +#define TDA_SERIALIZER MKREG(0x02, 0x03) +#define TDA_BUFFER_OUT MKREG(0x02, 0x04) +#define TDA_PLL_SCG1 MKREG(0x02, 0x05) +#define TDA_PLL_SCG2 MKREG(0x02, 0x06) +#define TDA_PLL_SCGN1 MKREG(0x02, 0x07) +#define TDA_PLL_SCGN2 MKREG(0x02, 0x08) +#define TDA_PLL_SCGR1 MKREG(0x02, 0x09) +#define TDA_PLL_SCGR2 MKREG(0x02, 0x0a) + +#define TDA_SEL_CLK MKREG(0x02, 0x11) +#define SEL_CLK_ENA_SC_CLK (1 << 3) +#define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) +#define SEL_CLK_SEL_CLK1 (1 << 0) +#define TDA_ANA_GENERAL MKREG(0x02, 0x12) + +#define TDA_EDID_DATA0 MKREG(0x09, 0x00) +#define TDA_EDID_CTRL MKREG(0x09, 0xfa) +#define TDA_DDC_ADDR MKREG(0x09, 0xfb) +#define TDA_DDC_OFFS MKREG(0x09, 0xfc) +#define TDA_DDC_SEGM_ADDR MKREG(0x09, 0xfd) +#define TDA_DDC_SEGM MKREG(0x09, 0xfe) + +#define TDA_IF_VSP MKREG(0x10, 0x20) +#define TDA_IF_AVI MKREG(0x10, 0x40) +#define TDA_IF_SPD MKREG(0x10, 0x60) +#define TDA_IF_AUD MKREG(0x10, 0x80) +#define TDA_IF_MPS MKREG(0x10, 0xa0) + +#define TDA_ENC_CNTRL MKREG(0x11, 0x0d) +#define ENC_CNTRL_DVI_MODE (0 << 2) +#define ENC_CNTRL_HDMI_MODE (1 << 2) +#define TDA_DIP_IF_FLAGS MKREG(0x11, 0x0f) +#define DIP_IF_FLAGS_IF5 (1 << 5) +#define DIP_IF_FLAGS_IF4 (1 << 4) +#define DIP_IF_FLAGS_IF3 (1 << 3) +#define DIP_IF_FLAGS_IF2 (1 << 2) /* AVI IF on page 10h */ +#define DIP_IF_FLAGS_IF1 (1 << 1) + +#define TDA_TX3 MKREG(0x12, 0x9a) +#define TDA_TX4 MKREG(0x12, 0x9b) +#define TX4_PD_RAM (1 << 1) +#define TDA_HDCP_TX33 MKREG(0x12, 0xb8) +#define HDCP_TX33_HDMI (1 << 1) + +#define TDA_CURPAGE_ADDR 0xff + +#define TDA_CEC_ENAMODS 0xff +#define ENAMODS_RXSENS (1 << 2) +#define ENAMODS_HDMI (1 << 1) +#define TDA_CEC_FRO_IM_CLK_CTRL 0xfb +#define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) +#define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) + +/* EDID reading */ +#define EDID_LENGTH 0x80 +#define MAX_READ_ATTEMPTS 100 + +/* EDID fields */ +#define EDID_MODES0 35 +#define EDID_MODES1 36 +#define EDID_TIMING_START 38 +#define EDID_TIMING_END 54 +#define EDID_TIMING_X(v) (((v) + 31) * 8) +#define EDID_FREQ(v) (((v) & 0x3f) + 60) +#define EDID_RATIO(v) (((v) >> 6) & 0x3) +#define EDID_RATIO_10x16 0 +#define EDID_RATIO_3x4 1 +#define EDID_RATIO_4x5 2 +#define EDID_RATIO_9x16 3 + +#define TDA19988 0x0301 + +struct tda19988_softc { + device_t sc_dev; + uint32_t sc_addr; + uint32_t sc_cec_addr; + uint16_t sc_version; + struct intr_config_hook enum_hook; + int sc_current_page; + uint8_t *sc_edid; + uint32_t sc_edid_len; +}; + +static int +tda19988_set_page(struct tda19988_softc *sc, uint8_t page) +{ + uint8_t addr = TDA_CURPAGE_ADDR; + uint8_t cmd[2]; + int result; + struct iic_msg msg[] = { + { sc->sc_addr, IIC_M_WR, 2, cmd }, + }; + + cmd[0] = addr; + cmd[1] = page; + + result = (iicbus_transfer(sc->sc_dev, msg, 1)); + if (result) + printf("tda19988_set_page failed: %d\n", result); + else + sc->sc_current_page = page; + + return (result); +} + +static int +tda19988_cec_read(struct tda19988_softc *sc, uint8_t addr, uint8_t *data) +{ + int result; + struct iic_msg msg[] = { + { sc->sc_cec_addr, IIC_M_WR, 1, &addr }, + { sc->sc_cec_addr, IIC_M_RD, 1, data }, + }; + + result = iicbus_transfer(sc->sc_dev, msg, 2); + if (result) + printf("tda19988_cec_read failed: %d\n", result); + return (result); +} + +static int +tda19988_cec_write(struct tda19988_softc *sc, uint8_t address, uint8_t data) +{ + uint8_t cmd[2]; + int result; + struct iic_msg msg[] = { + { sc->sc_cec_addr, IIC_M_WR, 2, cmd }, + }; + + cmd[0] = address; + cmd[1] = data; + + result = iicbus_transfer(sc->sc_dev, msg, 1); + if (result) + printf("tda19988_cec_write failed: %d\n", result); + return (result); +} + +static int +tda19988_block_read(struct tda19988_softc *sc, uint16_t addr, uint8_t *data, int len) +{ + uint8_t reg; + int result; + struct iic_msg msg[] = { + { sc->sc_addr, IIC_M_WR, 1, ® }, + { sc->sc_addr, IIC_M_RD, len, data }, + }; + + reg = REGADDR(addr); + + if (sc->sc_current_page != REGPAGE(addr)) + tda19988_set_page(sc, REGPAGE(addr)); + + result = (iicbus_transfer(sc->sc_dev, msg, 2)); + if (result) + device_printf(sc->sc_dev, "tda19988_block_read failed: %d\n", result); + return (result); +} + +static int +tda19988_reg_read(struct tda19988_softc *sc, uint16_t addr, uint8_t *data) +{ + uint8_t reg; + int result; + struct iic_msg msg[] = { + { sc->sc_addr, IIC_M_WR, 1, ® }, + { sc->sc_addr, IIC_M_RD, 1, data }, + }; + + reg = REGADDR(addr); + + if (sc->sc_current_page != REGPAGE(addr)) + tda19988_set_page(sc, REGPAGE(addr)); + + result = (iicbus_transfer(sc->sc_dev, msg, 2)); + if (result) + device_printf(sc->sc_dev, "tda19988_reg_read failed: %d\n", result); + return (result); +} + +static int +tda19988_reg_write(struct tda19988_softc *sc, uint16_t address, uint8_t data) +{ + uint8_t cmd[2]; + int result; + struct iic_msg msg[] = { + { sc->sc_addr, IIC_M_WR, 2, cmd }, + }; + + cmd[0] = REGADDR(address); + cmd[1] = data; + + if (sc->sc_current_page != REGPAGE(address)) + tda19988_set_page(sc, REGPAGE(address)); + + result = iicbus_transfer(sc->sc_dev, msg, 1); + if (result) + device_printf(sc->sc_dev, "tda19988_reg_write failed: %d\n", result); + + return (result); +} + +static int +tda19988_reg_write2(struct tda19988_softc *sc, uint16_t address, uint16_t data) +{ + uint8_t cmd[3]; + int result; + struct iic_msg msg[] = { + { sc->sc_addr, IIC_M_WR, 3, cmd }, + }; + + cmd[0] = REGADDR(address); + cmd[1] = (data >> 8); + cmd[2] = (data & 0xff); + + if (sc->sc_current_page != REGPAGE(address)) + tda19988_set_page(sc, REGPAGE(address)); + + result = iicbus_transfer(sc->sc_dev, msg, 1); + if (result) + device_printf(sc->sc_dev, "tda19988_reg_write2 failed: %d\n", result); + + return (result); +} + +static void +tda19988_reg_set(struct tda19988_softc *sc, uint16_t addr, uint8_t flags) +{ + uint8_t data; + + tda19988_reg_read(sc, addr, &data); + data |= flags; + tda19988_reg_write(sc, addr, data); +} + +static void +tda19988_reg_clear(struct tda19988_softc *sc, uint16_t addr, uint8_t flags) +{ + uint8_t data; + + tda19988_reg_read(sc, addr, &data); + data &= ~flags; + tda19988_reg_write(sc, addr, data); +} + +static int +tda19988_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "nxp,tda998x")) + return (ENXIO); + + return (BUS_PROBE_DEFAULT); +} + +static void +tda19988_init_encoder(struct tda19988_softc *sc, const struct videomode *mode) +{ + uint16_t ref_pix, ref_line, n_pix, n_line; + uint16_t hs_pix_start, hs_pix_stop; + uint16_t vs1_pix_start, vs1_pix_stop; + uint16_t vs1_line_start, vs1_line_end; + uint16_t vs2_pix_start, vs2_pix_stop; + uint16_t vs2_line_start, vs2_line_end; + uint16_t vwin1_line_start, vwin1_line_end; + uint16_t vwin2_line_start, vwin2_line_end; + uint16_t de_start, de_stop; + uint8_t reg, div; + + n_pix = mode->htotal; + n_line = mode->vtotal; + + hs_pix_stop = mode->hsync_end - mode->hdisplay; + hs_pix_start = mode->hsync_start - mode->hdisplay; + + de_stop = mode->htotal; + de_start = mode->htotal - mode->hdisplay; + ref_pix = hs_pix_start + 3; + + if (mode->flags & VID_HSKEW) + ref_pix += mode->hskew; + + if ((mode->flags & VID_INTERLACE) == 0) { + ref_line = 1 + mode->vsync_start - mode->vdisplay; + vwin1_line_start = mode->vtotal - mode->vdisplay - 1; + vwin1_line_end = vwin1_line_start + mode->vdisplay; + + vs1_pix_start = vs1_pix_stop = hs_pix_start; + vs1_line_start = mode->vsync_start - mode->vdisplay; + vs1_line_end = vs1_line_start + mode->vsync_end - mode->vsync_start; + + vwin2_line_start = vwin2_line_end = 0; + vs2_pix_start = vs2_pix_stop = 0; + vs2_line_start = vs2_line_end = 0; + } else { + ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2; + vwin1_line_start = (mode->vtotal - mode->vdisplay)/2; + vwin1_line_end = vwin1_line_start + mode->vdisplay/2; + + vs1_pix_start = vs1_pix_stop = hs_pix_start; + vs1_line_start = (mode->vsync_start - mode->vdisplay)/2; + vs1_line_end = vs1_line_start + (mode->vsync_end - mode->vsync_start)/2; + + vwin2_line_start = vwin1_line_start + mode->vtotal/2; + vwin2_line_end = vwin2_line_start + mode->vdisplay/2; + + vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2; + vs2_line_start = vs1_line_start + mode->vtotal/2 ; + vs2_line_end = vs2_line_start + (mode->vsync_end - mode->vsync_start)/2; + } + + div = 148500 / mode->dot_clock; + if (div != 0) { + div--; + if (div > 3) + div = 3; + } + + /* set HDMI HDCP mode off */ + tda19988_reg_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS); + tda19988_reg_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI); + tda19988_reg_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE); + + /* no pre-filter or interpolator */ + tda19988_reg_write(sc, TDA_HVF_CNTRL_0, + HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE); + tda19988_reg_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0)); + tda19988_reg_write(sc, TDA_VIP_CNTRL_4, + VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE); + + tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR); + tda19988_reg_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP); + tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE); + tda19988_reg_write(sc, TDA_SERIALIZER, 0); + tda19988_reg_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL); + + tda19988_reg_write(sc, TDA_RPT_CNTRL, 0); + tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) | + SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); + + tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) | + PLL_SERIAL_2_SRL_PR(0)); + + tda19988_reg_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP); + + tda19988_reg_write(sc, TDA_ANA_GENERAL, 0x09); + + tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD); + + /* + * Sync on rising HSYNC/VSYNC + */ + reg = VIP_CNTRL_3_SYNC_HS; + if (mode->flags & VID_NHSYNC) + reg |= VIP_CNTRL_3_H_TGL; + if (mode->flags & VID_NVSYNC) + reg |= VIP_CNTRL_3_V_TGL; + tda19988_reg_write(sc, TDA_VIP_CNTRL_3, reg); + + reg = TBG_CNTRL_1_TGL_EN; + if (mode->flags & VID_NHSYNC) + reg |= TBG_CNTRL_1_H_TGL; + if (mode->flags & VID_NVSYNC) + reg |= TBG_CNTRL_1_V_TGL; + tda19988_reg_write(sc, TDA_TBG_CNTRL_1, reg); + + /* Program timing */ + tda19988_reg_write(sc, TDA_VIDFORMAT, 0x00); + + tda19988_reg_write2(sc, TDA_REFPIX_MSB, ref_pix); + tda19988_reg_write2(sc, TDA_REFLINE_MSB, ref_line); + tda19988_reg_write2(sc, TDA_NPIX_MSB, n_pix); + tda19988_reg_write2(sc, TDA_NLINE_MSB, n_line); + + tda19988_reg_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start); + tda19988_reg_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start); + tda19988_reg_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end); + tda19988_reg_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop); + tda19988_reg_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start); + tda19988_reg_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start); + tda19988_reg_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end); + tda19988_reg_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop); + tda19988_reg_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start); + tda19988_reg_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop); + tda19988_reg_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start); + tda19988_reg_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end); + tda19988_reg_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start); + tda19988_reg_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end); + tda19988_reg_write2(sc, TDA_DE_START_MSB, de_start); + tda19988_reg_write2(sc, TDA_DE_STOP_MSB, de_stop); + + if (sc->sc_version == TDA19988) + tda19988_reg_write(sc, TDA_ENABLE_SPACE, 0x00); + + /* must be last register set */ + tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE); +} + +static int +tda19988_read_edid_block(struct tda19988_softc *sc, uint8_t *buf, int block) +{ + int attempt, err; + uint8_t data; + + err = 0; + + tda19988_reg_set(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); + + /* Block 0 */ + tda19988_reg_write(sc, TDA_DDC_ADDR, 0xa0); + tda19988_reg_write(sc, TDA_DDC_OFFS, (block % 2) ? 128 : 0); + tda19988_reg_write(sc, TDA_DDC_SEGM_ADDR, 0x60); + tda19988_reg_write(sc, TDA_DDC_SEGM, block / 2); + + tda19988_reg_write(sc, TDA_EDID_CTRL, 1); + tda19988_reg_write(sc, TDA_EDID_CTRL, 0); + + data = 0; + for (attempt = 0; attempt < MAX_READ_ATTEMPTS; attempt++) { + tda19988_reg_read(sc, TDA_INT_FLAGS_2, &data); + if (data & INT_FLAGS_2_EDID_BLK_RD) + break; + pause("EDID", 1); + } + + if (attempt == MAX_READ_ATTEMPTS) { + err = -1; + goto done; + } + + if (tda19988_block_read(sc, TDA_EDID_DATA0, buf, EDID_LENGTH) != 0) { + err = -1; + goto done; + } + +done: + tda19988_reg_clear(sc, TDA_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); + + return (err); +} + +static int +tda19988_read_edid(struct tda19988_softc *sc) +{ + int err; + int blocks, i; + uint8_t *buf; + + err = 0; + if (sc->sc_version == TDA19988) + tda19988_reg_clear(sc, TDA_TX4, TX4_PD_RAM); + + err = tda19988_read_edid_block(sc, sc->sc_edid, 0); + if (err) + goto done; + + blocks = sc->sc_edid[0x7e]; + if (blocks > 0) { + sc->sc_edid = realloc(sc->sc_edid, + EDID_LENGTH*(blocks+1), M_DEVBUF, M_WAITOK); + sc->sc_edid_len = EDID_LENGTH*(blocks+1); + for (i = 0; i < blocks; i++) { + /* TODO: check validity */ + buf = sc->sc_edid + EDID_LENGTH*(i+1); + err = tda19988_read_edid_block(sc, buf, i); + if (err) + goto done; + } + } + + EVENTHANDLER_INVOKE(hdmi_event, 0); +done: + if (sc->sc_version == TDA19988) + tda19988_reg_set(sc, TDA_TX4, TX4_PD_RAM); + + return (err); +} + +static void +tda19988_start(void *xdev) +{ + struct tda19988_softc *sc; + device_t dev = (device_t)xdev; + uint8_t data; + uint16_t version; + + sc = device_get_softc(dev); + + tda19988_cec_write(sc, TDA_CEC_ENAMODS, ENAMODS_RXSENS | ENAMODS_HDMI); + DELAY(1000); + tda19988_cec_read(sc, 0xfe, &data); + + /* Reset core */ + tda19988_reg_set(sc, TDA_SOFTRESET, 3); + DELAY(100); + tda19988_reg_clear(sc, TDA_SOFTRESET, 3); + DELAY(100); + + /* reset transmitter: */ + tda19988_reg_set(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR); + tda19988_reg_clear(sc, TDA_MAIN_CNTRL0, MAIN_CNTRL0_SR); + + /* PLL registers common configuration */ + tda19988_reg_write(sc, TDA_PLL_SERIAL_1, 0x00); + tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); + tda19988_reg_write(sc, TDA_PLL_SERIAL_3, 0x00); + tda19988_reg_write(sc, TDA_SERIALIZER, 0x00); + tda19988_reg_write(sc, TDA_BUFFER_OUT, 0x00); + tda19988_reg_write(sc, TDA_PLL_SCG1, 0x00); + tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); + tda19988_reg_write(sc, TDA_PLL_SCGN1, 0xfa); + tda19988_reg_write(sc, TDA_PLL_SCGN2, 0x00); + tda19988_reg_write(sc, TDA_PLL_SCGR1, 0x5b); + tda19988_reg_write(sc, TDA_PLL_SCGR2, 0x00); + tda19988_reg_write(sc, TDA_PLL_SCG2, 0x10); + + /* Write the default value MUX register */ + tda19988_reg_write(sc, TDA_MUX_VP_VIP_OUT, 0x24); + + version = 0; + tda19988_reg_read(sc, TDA_VERSION, &data); + version |= data; + tda19988_reg_read(sc, TDA_VERSION_MSB, &data); + version |= (data << 8); + + /* Clear feature bits */ + sc->sc_version = version & ~0x30; + switch (sc->sc_version) { + case TDA19988: + device_printf(dev, "TDA19988\n"); + break; + default: + device_printf(dev, "Unknown device: %04x\n", sc->sc_version); + goto done; + } + + tda19988_reg_write(sc, TDA_DDC_CTRL, DDC_ENABLE); + tda19988_reg_write(sc, TDA_TX3, 39); + + tda19988_cec_write(sc, TDA_CEC_FRO_IM_CLK_CTRL, + CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); + + if (tda19988_read_edid(sc) < 0) { + device_printf(dev, "failed to read EDID\n"); + goto done; + } + + /* Default values for RGB 4:4:4 mapping */ + tda19988_reg_write(sc, TDA_VIP_CNTRL_0, 0x23); + tda19988_reg_write(sc, TDA_VIP_CNTRL_1, 0x45); + tda19988_reg_write(sc, TDA_VIP_CNTRL_2, 0x01); + +done: + config_intrhook_disestablish(&sc->enum_hook); +} + +static int +tda19988_attach(device_t dev) +{ + struct tda19988_softc *sc; + phandle_t node; + + sc = device_get_softc(dev); + + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev) << 1; + sc->sc_cec_addr = (0x34 << 1); /* hardcoded */ + sc->sc_edid = malloc(EDID_LENGTH, M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_edid_len = EDID_LENGTH; + + device_set_desc(dev, "NXP TDA19988 HDMI transmitter"); + + sc->enum_hook.ich_func = tda19988_start; + sc->enum_hook.ich_arg = dev; + + if (config_intrhook_establish(&sc->enum_hook) != 0) + return (ENOMEM); + + node = ofw_bus_get_node(dev); + OF_device_register_xref(OF_xref_from_node(node), dev); + + return (0); +} + +static int +tda19988_detach(device_t dev) +{ + + /* XXX: Do not let unload drive */ + return (EBUSY); +} + +static int +tda19988_get_edid(device_t dev, uint8_t **edid, uint32_t *edid_len) +{ + struct tda19988_softc *sc; + + sc = device_get_softc(dev); + + if (sc->sc_edid) { + *edid = sc->sc_edid; + *edid_len = sc->sc_edid_len; + } else + return (ENXIO); + + return (0); +} + +static int +tda19988_set_videomode(device_t dev, const struct videomode *mode) +{ + struct tda19988_softc *sc; + + sc = device_get_softc(dev); + + tda19988_init_encoder(sc, mode); + + return (0); +} + +static device_method_t tda_methods[] = { + DEVMETHOD(device_probe, tda19988_probe), + DEVMETHOD(device_attach, tda19988_attach), + DEVMETHOD(device_detach, tda19988_detach), + + /* HDMI methods */ + DEVMETHOD(hdmi_get_edid, tda19988_get_edid), + DEVMETHOD(hdmi_set_videomode, tda19988_set_videomode), + {0, 0}, +}; + +static driver_t tda_driver = { + "tda", + tda_methods, + sizeof(struct tda19988_softc), +}; + +static devclass_t tda_devclass; + +DRIVER_MODULE(tda, iicbus, tda_driver, tda_devclass, 0, 0); +MODULE_VERSION(tda, 1); +MODULE_DEPEND(tda, iicbus, 1, 1, 1); diff --git a/sys/arm/ti/am335x/tps65217x.h b/sys/arm/ti/am335x/tps65217x.h index 96f16dd..cdeca25 100644 --- a/sys/arm/ti/am335x/tps65217x.h +++ b/sys/arm/ti/am335x/tps65217x.h @@ -34,7 +34,7 @@ * TPS65217 PMIC is a companion chip for AM335x SoC sitting on I2C bus */ -/* TPS65217 Reisters */ +/* TPS65217 Registers */ #define TPS65217_CHIPID_REG 0x00 struct tps65217_chipid_reg { unsigned int rev:4; diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c index 8b1cb6e..fc5fb97 100644 --- a/sys/arm/ti/omap4/omap4_prcm_clks.c +++ b/sys/arm/ti/omap4/omap4_prcm_clks.c @@ -217,7 +217,8 @@ static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_generic_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_generic_get_source_freq \ + .clk_get_source_freq = omap4_clk_generic_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_GPTIMER_CLOCK_DEV(i) \ @@ -226,7 +227,8 @@ static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_gptimer_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_gptimer_get_source_freq \ + .clk_get_source_freq = omap4_clk_gptimer_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_HSMMC_CLOCK_DEV(i) \ @@ -235,7 +237,8 @@ static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_hsmmc_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq \ + .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_HSUSBHOST_CLOCK_DEV(i) \ @@ -244,7 +247,8 @@ static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int .clk_deactivate = omap4_clk_hsusbhost_deactivate, \ .clk_set_source = omap4_clk_hsusbhost_set_source, \ .clk_accessible = omap4_clk_hsusbhost_accessible, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } @@ -257,6 +261,7 @@ struct ti_clock_dev ti_omap4_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = omap4_clk_get_sysclk_freq, + .clk_set_source_freq = NULL, }, /* MPU (ARM) core clocks */ { .id = MPU_CLK, @@ -265,6 +270,7 @@ struct ti_clock_dev ti_omap4_clk_devmap[] = { .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = omap4_clk_get_arm_fclk_freq, + .clk_set_source_freq = NULL, }, diff --git a/sys/arm/ti/ti_prcm.c b/sys/arm/ti/ti_prcm.c index 3c073f9..c5ab9c7 100644 --- a/sys/arm/ti/ti_prcm.c +++ b/sys/arm/ti/ti_prcm.c @@ -285,7 +285,7 @@ ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc) * @clk: identifier for the module to enable, see ti_prcm.h for a list * of possible modules. * @freq: pointer to an integer that upon return will contain the src freq - * + * * This function returns the frequency of the source clock. * * The real work done to enable the clock is really done in the callback @@ -319,6 +319,39 @@ ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq) ret = clk_dev->clk_get_source_freq(clk_dev, freq); else ret = EINVAL; - + + return (ret); +} + +/** + * ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible + * @clk: identifier for the module to enable, see ti_prcm.h for a list + * of possible modules. + * @freq: requested freq + * + * LOCKING: + * Internally locks the driver context. + * + * RETURNS: + * Returns 0 on success or positive error code on failure. + */ +int +ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq) +{ + struct ti_clock_dev *clk_dev; + int ret; + + clk_dev = ti_prcm_clk_dev(clk); + + /* Sanity check we managed to find the clock */ + if (clk_dev == NULL) + return (EINVAL); + + /* Get the source frequency of the clock */ + if (clk_dev->clk_set_source_freq) + ret = clk_dev->clk_set_source_freq(clk_dev, freq); + else + ret = EINVAL; + return (ret); } diff --git a/sys/arm/ti/ti_prcm.h b/sys/arm/ti/ti_prcm.h index eaea990..c40439a 100644 --- a/sys/arm/ti/ti_prcm.h +++ b/sys/arm/ti/ti_prcm.h @@ -184,6 +184,8 @@ struct ti_clock_dev { int (*clk_set_source)(struct ti_clock_dev *clkdev, clk_src_t clksrc); int (*clk_accessible)(struct ti_clock_dev *clkdev); + int (*clk_set_source_freq)(struct ti_clock_dev *clkdev, + unsigned int freq); int (*clk_get_source_freq)(struct ti_clock_dev *clkdev, unsigned int *freq); }; @@ -194,6 +196,7 @@ int ti_prcm_clk_disable(clk_ident_t clk); int ti_prcm_clk_accessible(clk_ident_t clk); int ti_prcm_clk_disable_autoidle(clk_ident_t clk); int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc); +int ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq); int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq); void ti_prcm_reset(void); diff --git a/sys/arm64/acpica/OsdEnvironment.c b/sys/arm64/acpica/OsdEnvironment.c new file mode 100644 index 0000000..79dc212 --- /dev/null +++ b/sys/arm64/acpica/OsdEnvironment.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2000,2001 Michael Smith + * Copyright (c) 2000 BSDi + * 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/types.h> +#include <sys/bus.h> +#include <sys/sysctl.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/actables.h> + +static u_long acpi_root_phys; + +SYSCTL_ULONG(_machdep, OID_AUTO, acpi_root, CTLFLAG_RD, &acpi_root_phys, 0, + "The physical address of the RSDP"); + +ACPI_STATUS +AcpiOsInitialize(void) +{ + + return (AE_OK); +} + +ACPI_STATUS +AcpiOsTerminate(void) +{ + + return (AE_OK); +} + +static u_long +acpi_get_root_from_loader(void) +{ + long acpi_root; + + if (resource_long_value("acpi", 0, "rsdp", &acpi_root) == 0) + return (acpi_root); + + return (0); +} + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer(void) +{ + + if (acpi_root_phys == 0) + acpi_root_phys = acpi_get_root_from_loader(); + + return (acpi_root_phys); +} diff --git a/sys/arm64/acpica/acpi_machdep.c b/sys/arm64/acpica/acpi_machdep.c new file mode 100644 index 0000000..da07cfc --- /dev/null +++ b/sys/arm64/acpica/acpi_machdep.c @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2001 Mitsuru IWASAKI + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/actables.h> + +#include <dev/acpica/acpivar.h> + +int +acpi_machdep_init(device_t dev) +{ + + return (0); +} + +int +acpi_machdep_quirks(int *quirks) +{ + + return (0); +} + +static void * +map_table(vm_paddr_t pa, int offset, const char *sig) +{ + ACPI_TABLE_HEADER *header; + vm_offset_t length; + void *table; + + header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER)); + if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + return (NULL); + } + length = header->Length; + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + + table = pmap_mapbios(pa, length); + if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { + if (bootverbose) + printf("ACPI: Failed checksum for table %s\n", sig); +#if (ACPI_CHECKSUM_ABORT) + pmap_unmapbios(table, length); + return (NULL); +#endif + } + return (table); +} + +/* + * See if a given ACPI table is the requested table. Returns the + * length of the able if it matches or zero on failure. + */ +static int +probe_table(vm_paddr_t address, const char *sig) +{ + ACPI_TABLE_HEADER *table; + + table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER)); + if (table == NULL) { + if (bootverbose) + printf("ACPI: Failed to map table at 0x%jx\n", + (uintmax_t)address); + return (0); + } + if (bootverbose) + printf("Table '%.4s' at 0x%jx\n", table->Signature, + (uintmax_t)address); + + if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) { + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (0); + } + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (1); +} + +/* Unmap a table previously mapped via acpi_map_table(). */ +void +acpi_unmap_table(void *table) +{ + ACPI_TABLE_HEADER *header; + + header = (ACPI_TABLE_HEADER *)table; + pmap_unmapbios((vm_offset_t)table, header->Length); +} + +/* + * Try to map a table at a given physical address previously returned + * by acpi_find_table(). + */ +void * +acpi_map_table(vm_paddr_t pa, const char *sig) +{ + + return (map_table(pa, 0, sig)); +} + +/* + * Return the physical address of the requested table or zero if one + * is not found. + */ +vm_paddr_t +acpi_find_table(const char *sig) +{ + ACPI_PHYSICAL_ADDRESS rsdp_ptr; + ACPI_TABLE_RSDP *rsdp; + ACPI_TABLE_XSDT *xsdt; + ACPI_TABLE_HEADER *table; + vm_paddr_t addr; + int i, count; + + if (resource_disabled("acpi", 0)) + return (0); + + /* + * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn + * calls pmap_mapbios() to find the RSDP, we assume that we can use + * pmap_mapbios() to map the RSDP. + */ + if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) + return (0); + rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); + if (rsdp == NULL) { + if (bootverbose) + printf("ACPI: Failed to map RSDP\n"); + return (0); + } + + addr = 0; + if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { + /* + * AcpiOsGetRootPointer only verifies the checksum for + * the version 1.0 portion of the RSDP. Version 2.0 has + * an additional checksum that we verify first. + */ + if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { + if (bootverbose) + printf("ACPI: RSDP failed extended checksum\n"); + return (0); + } + xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); + if (xsdt == NULL) { + if (bootverbose) + printf("ACPI: Failed to map XSDT\n"); + pmap_unmapbios((vm_offset_t)rsdp, + sizeof(ACPI_TABLE_RSDP)); + return (0); + } + count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / + sizeof(UINT64); + for (i = 0; i < count; i++) + if (probe_table(xsdt->TableOffsetEntry[i], sig)) { + addr = xsdt->TableOffsetEntry[i]; + break; + } + acpi_unmap_table(xsdt); + } + pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); + + if (addr == 0) { + if (bootverbose) + printf("ACPI: No %s table found\n", sig); + return (0); + } + if (bootverbose) + printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr); + + /* + * Verify that we can map the full table and that its checksum is + * correct, etc. + */ + table = map_table(addr, 0, sig); + if (table == NULL) + return (0); + acpi_unmap_table(table); + + return (addr); +} diff --git a/sys/arm64/acpica/acpi_wakeup.c b/sys/arm64/acpica/acpi_wakeup.c new file mode 100644 index 0000000..7724fdd --- /dev/null +++ b/sys/arm64/acpica/acpi_wakeup.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> + +#include <contrib/dev/acpica/include/acpi.h> + +#include <dev/acpica/acpivar.h> + +/* + * ARM64TODO: Implement this. + */ +int +acpi_sleep_machdep(struct acpi_softc *sc, int state) +{ + + return (-1); +} + +int +acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, + int intr_enabled) +{ + + /* ARM64TODO: We will need this with acpi_sleep_machdep */ + KASSERT(sleep_result == -1, + ("acpi_wakeup_machdep: Invalid sleep result")); + + return (sleep_result); +} diff --git a/sys/arm64/arm64/db_interface.c b/sys/arm64/arm64/db_interface.c index 38834af..e40802f 100644 --- a/sys/arm64/arm64/db_interface.c +++ b/sys/arm64/arm64/db_interface.c @@ -156,13 +156,11 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) } *dst++ = *data++; } + dsb(ish); - dsb(); /* Clean D-cache and invalidate I-cache */ cpu_dcache_wb_range(addr, (vm_size_t)size); cpu_icache_sync_range(addr, (vm_size_t)size); - dsb(); - isb(); return (0); } diff --git a/sys/arm64/arm64/db_trace.c b/sys/arm64/arm64/db_trace.c index 1e89bac..c606377 100644 --- a/sys/arm64/arm64/db_trace.c +++ b/sys/arm64/arm64/db_trace.c @@ -38,12 +38,7 @@ __FBSDID("$FreeBSD$"); #include <machine/armreg.h> #include <machine/debug_monitor.h> - -struct unwind_state { - uint64_t fp; - uint64_t sp; - uint64_t pc; -}; +#include <machine/stack.h> void db_md_list_watchpoints() @@ -67,22 +62,6 @@ db_md_set_watchpoint(db_expr_t addr, db_expr_t size) HW_BREAKPOINT_RW)); } -static int -db_unwind_frame(struct unwind_state *frame) -{ - uint64_t fp = frame->fp; - - if (fp == 0) - return -1; - - frame->sp = fp + 0x10; - /* FP to previous frame (X29) */ - frame->fp = *(uint64_t *)(fp); - /* LR (X30) */ - frame->pc = *(uint64_t *)(fp + 8) - 4; - return (0); -} - static void db_stack_trace_cmd(struct unwind_state *frame) { @@ -95,7 +74,7 @@ db_stack_trace_cmd(struct unwind_state *frame) uint64_t pc = frame->pc; int ret; - ret = db_unwind_frame(frame); + ret = unwind_frame(frame); if (ret < 0) break; diff --git a/sys/arm64/arm64/gic.c b/sys/arm64/arm64/gic.c index 59fac99..7c0692e 100644 --- a/sys/arm64/arm64/gic.c +++ b/sys/arm64/arm64/gic.c @@ -51,11 +51,7 @@ __FBSDID("$FreeBSD$"); #include <machine/intr.h> #include <machine/smp.h> -#include <dev/fdt/fdt_common.h> -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> - +#include <arm64/arm64/gic.h> #include "pic_if.h" @@ -102,18 +98,6 @@ __FBSDID("$FreeBSD$"); #define GICD_ICFGR_TRIG_EDGE (1 << 1) #define GICD_ICFGR_TRIG_MASK 0x2 -struct arm_gic_softc { - device_t gic_dev; - struct resource * gic_res[3]; - bus_space_tag_t gic_c_bst; - bus_space_tag_t gic_d_bst; - bus_space_handle_t gic_c_bsh; - bus_space_handle_t gic_d_bsh; - uint8_t ver; - struct mtx mutex; - uint32_t nirqs; -}; - static struct resource_spec arm_gic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ @@ -136,31 +120,6 @@ static pic_eoi_t gic_eoi; static pic_mask_t gic_mask_irq; static pic_unmask_t gic_unmask_irq; -static struct ofw_compat_data compat_data[] = { - {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ - {"arm,gic-400", true}, - {"arm,cortex-a15-gic", true}, - {"arm,cortex-a9-gic", true}, - {"arm,cortex-a7-gic", true}, - {"arm,arm11mp-gic", true}, - {"brcm,brahma-b15-gic", true}, - {NULL, false} -}; - -static int -arm_gic_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) - return (ENXIO); - - device_set_desc(dev, "ARM Generic Interrupt Controller"); - return (BUS_PROBE_DEFAULT); -} - #ifdef SMP static void gic_init_secondary(device_t dev) @@ -367,7 +326,6 @@ arm_gic_ipi_clear(device_t dev, int ipi) static device_method_t arm_gic_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, arm_gic_probe), DEVMETHOD(device_attach, arm_gic_attach), /* pic_if */ @@ -384,15 +342,5 @@ static device_method_t arm_gic_methods[] = { { 0, 0 } }; -static driver_t arm_gic_driver = { - "gic", - arm_gic_methods, - sizeof(struct arm_gic_softc), -}; - -static devclass_t arm_gic_devclass; - -EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); -EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods, + sizeof(struct arm_gic_softc)); diff --git a/sys/arm64/arm64/gic.h b/sys/arm64/arm64/gic.h new file mode 100644 index 0000000..2660884 --- /dev/null +++ b/sys/arm64/arm64/gic.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Developed by Damjan Marion <damjan.marion@gmail.com> + * + * Based on OMAP4 GIC code by Ben Gray + * + * 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. 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 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 _ARM64_GIC_H_ +#define _ARM64_GIC_H_ + +DECLARE_CLASS(arm_gic_driver); + +struct arm_gic_softc { + device_t gic_dev; + struct resource * gic_res[3]; + bus_space_tag_t gic_c_bst; + bus_space_tag_t gic_d_bst; + bus_space_handle_t gic_c_bsh; + bus_space_handle_t gic_d_bsh; + uint8_t ver; + struct mtx mutex; + uint32_t nirqs; +}; + +#endif diff --git a/sys/arm64/arm64/gic_acpi.c b/sys/arm64/arm64/gic_acpi.c new file mode 100644 index 0000000..ad26c0c --- /dev/null +++ b/sys/arm64/arm64/gic_acpi.c @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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$"); + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> + +#include <arm64/arm64/gic.h> + +#include <contrib/dev/acpica/include/acpi.h> + +#include <dev/acpica/acpivar.h> + +struct arm_gic_acpi_softc { + struct arm_gic_softc gic_sc; + struct resource_list res; +}; + +struct madt_table_data { + device_t parent; + ACPI_MADT_GENERIC_DISTRIBUTOR *dist; + ACPI_MADT_GENERIC_INTERRUPT *intr; +}; + +static void +madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + struct madt_table_data *madt_data; + + madt_data = (struct madt_table_data *)arg; + + switch(entry->Type) { + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + if (madt_data->intr != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have an interrupt table"); + break; + } + + madt_data->intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry; + break; + + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + if (madt_data->dist != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have a distributor table"); + break; + } + + madt_data->dist = (ACPI_MADT_GENERIC_DISTRIBUTOR *)entry; + break; + + default: + break; + } +} + +static void +arm_gic_acpi_identify(driver_t *driver, device_t parent) +{ + struct madt_table_data madt_data; + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + device_t dev; + + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return; + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(parent, "gic: Unable to map the MADT\n"); + return; + } + + madt_data.parent = parent; + madt_data.dist = NULL; + madt_data.intr = NULL; + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + madt_handler, &madt_data); + if (madt_data.intr == NULL || madt_data.dist == NULL) { + device_printf(parent, + "No gic interrupt or distributor table\n"); + goto out; + } + + dev = BUS_ADD_CHILD(parent, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE, + "gic", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + /* Add the MADT data */ + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 0, + madt_data.dist->BaseAddress, PAGE_SIZE); + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 1, + madt_data.intr->BaseAddress, PAGE_SIZE); + +out: + acpi_unmap_table(madt); +} + +static int +arm_gic_acpi_probe(device_t dev) +{ + + device_set_desc(dev, "ARM Generic Interrupt Controller"); + return (BUS_PROBE_NOWILDCARD); +} + +static device_method_t arm_gic_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, arm_gic_acpi_identify), + DEVMETHOD(device_probe, arm_gic_acpi_probe), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gic, arm_gic_acpi_driver, arm_gic_acpi_methods, + sizeof(struct arm_gic_acpi_softc), arm_gic_driver); + +static devclass_t arm_gic_acpi_devclass; + +EARLY_DRIVER_MODULE(gic, acpi, arm_gic_acpi_driver, + arm_gic_acpi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); diff --git a/sys/arm64/arm64/gic_fdt.c b/sys/arm64/arm64/gic_fdt.c new file mode 100644 index 0000000..5b70624 --- /dev/null +++ b/sys/arm64/arm64/gic_fdt.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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$"); + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm64/arm64/gic.h> + +static struct ofw_compat_data compat_data[] = { + {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ + {"arm,gic-400", true}, + {"arm,cortex-a15-gic", true}, + {"arm,cortex-a9-gic", true}, + {"arm,cortex-a7-gic", true}, + {"arm,arm11mp-gic", true}, + {"brcm,brahma-b15-gic", true}, + {NULL, false} +}; + +static int +arm_gic_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "ARM Generic Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static device_method_t arm_gic_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, arm_gic_fdt_probe), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gic, arm_gic_fdt_driver, arm_gic_fdt_methods, + sizeof(struct arm_gic_softc), arm_gic_driver); + +static devclass_t arm_gic_fdt_devclass; + +EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_fdt_driver, + arm_gic_fdt_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_fdt_driver, arm_gic_fdt_devclass, + 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 221b138..c36769d 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -392,6 +392,8 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate) void cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) { + + pcpu->pc_acpi_id = 0xffffffff; } void diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c index d6c6d2b..764012e 100644 --- a/sys/arm64/arm64/nexus.c +++ b/sys/arm64/arm64/nexus.c @@ -60,12 +60,17 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <machine/intr.h> +#include "opt_acpi.h" #include "opt_platform.h" #ifdef FDT #include <dev/fdt/fdt_common.h> #include "ofw_bus_if.h" #endif +#ifdef DEV_ACPI +#include <contrib/dev/acpica/include/acpi.h> +#include <dev/acpica/acpivar.h> +#endif extern struct bus_space memmap_bus; @@ -78,9 +83,19 @@ struct nexus_device { #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) static struct rman mem_rman; +static struct rman irq_rman; -static int nexus_probe(device_t); static int nexus_attach(device_t); + +#ifdef FDT +static device_probe_t nexus_fdt_probe; +static device_attach_t nexus_fdt_attach; +#endif +#ifdef DEV_ACPI +static device_probe_t nexus_acpi_probe; +static device_attach_t nexus_acpi_attach; +#endif + static int nexus_print_child(device_t, device_t); static device_t nexus_add_child(device_t, u_int, const char *, int); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, @@ -89,6 +104,8 @@ static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); +static struct resource_list *nexus_get_reslist(device_t, device_t); +static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_deactivate_resource(device_t, device_t, int, int, struct resource *); @@ -102,21 +119,18 @@ static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, #endif static device_method_t nexus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, nexus_probe), - DEVMETHOD(device_attach, nexus_attach), /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_get_resource_list, nexus_get_reslist), + DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), -#ifdef FDT - DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), -#endif + { 0, 0 } }; @@ -129,15 +143,6 @@ static driver_t nexus_driver = { DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); static int -nexus_probe(device_t dev) -{ - - device_quiet(dev); /* suppress attach message for neatness */ - - return (BUS_PROBE_DEFAULT); -} - -static int nexus_attach(device_t dev) { @@ -146,15 +151,14 @@ nexus_attach(device_t dev) mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "I/O memory addresses"; if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) - panic("nexus_probe mem_rman"); - - /* Add the ofwbus device */ - /* ARM64TODO: Alternatively add acpi */ - nexus_add_child(dev, 10, "ofwbus", 0); + panic("nexus_attach mem_rman"); + irq_rman.rm_start = 0; + irq_rman.rm_end = ~0ul; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupts"; + if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0)) + panic("nexus_attach irq_rman"); - /* - * First, deal with the children we know about already - */ bus_generic_probe(dev); bus_generic_attach(dev); @@ -201,11 +205,34 @@ static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { + struct nexus_device *ndev = DEVTONX(child); struct resource *rv; + struct resource_list_entry *rle; struct rman *rm; int needactivate = flags & RF_ACTIVE; + /* + * If this is an allocation of the "default" range for a given + * RID, and we know what the resources for this device are + * (ie. they aren't maintained by a child bus), then work out + * the start/end values. + */ + if ((start == 0UL) && (end == ~0UL) && (count == 1)) { + if (device_get_parent(child) != bus || ndev == NULL) + return(NULL); + rle = resource_list_find(&ndev->nx_resources, type, *rid); + if (rle == NULL) + return(NULL); + start = rle->start; + end = rle->end; + count = rle->count; + } + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + case SYS_RES_MEMORY: case SYS_RES_IOPORT: rm = &mem_rman; @@ -297,6 +324,28 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid, return (0); } +static struct resource_list * +nexus_get_reslist(device_t dev, device_t child) +{ + struct nexus_device *ndev = DEVTONX(child); + + return (&ndev->nx_resources); +} + +static int +nexus_set_resource(device_t dev, device_t child, int type, int rid, + u_long start, u_long count) +{ + struct nexus_device *ndev = DEVTONX(child); + struct resource_list *rl = &ndev->nx_resources; + + /* XXX this should return a success/failure indicator */ + resource_list_add(rl, type, rid, start, start + count - 1, count); + + return(0); +} + + static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) @@ -317,6 +366,41 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, } #ifdef FDT +static device_method_t nexus_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_fdt_probe), + DEVMETHOD(device_attach, nexus_fdt_attach), + + /* OFW interface */ + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), +}; + +#define nexus_baseclasses nexus_fdt_baseclasses +DEFINE_CLASS_1(nexus, nexus_fdt_driver, nexus_fdt_methods, 1, nexus_driver); +#undef nexus_baseclasses +static devclass_t nexus_fdt_devclass; + +DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass, 0, 0); + +static int +nexus_fdt_probe(device_t dev) +{ + + if (OF_peer(0) == 0) + return (ENXIO); + + device_quiet(dev); + return (BUS_PROBE_DEFAULT); +} + +static int +nexus_fdt_attach(device_t dev) +{ + + nexus_add_child(dev, 10, "ofwbus", 0); + return (nexus_attach(dev)); +} + static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) @@ -336,3 +420,37 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, } #endif +#ifdef DEV_ACPI +static device_method_t nexus_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_acpi_probe), + DEVMETHOD(device_attach, nexus_acpi_attach), +}; + +#define nexus_baseclasses nexus_acpi_baseclasses +DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, + nexus_driver); +#undef nexus_baseclasses +static devclass_t nexus_acpi_devclass; + +DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_acpi_devclass, 0, 0); + +static int +nexus_acpi_probe(device_t dev) +{ + + if (acpi_identify() != 0) + return (ENXIO); + + device_quiet(dev); + return (BUS_PROBE_LOW_PRIORITY); +} + +static int +nexus_acpi_attach(device_t dev) +{ + + nexus_add_child(dev, 10, "acpi", 0); + return (nexus_attach(dev)); +} +#endif diff --git a/sys/arm64/arm64/unwind.c b/sys/arm64/arm64/unwind.c new file mode 100644 index 0000000..13e0b54 --- /dev/null +++ b/sys/arm64/arm64/unwind.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of 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$"); +#include <sys/param.h> + +#include <machine/stack.h> + +int +unwind_frame(struct unwind_state *frame) +{ + uint64_t fp; + + fp = frame->fp; + if (fp == 0) + return (-1); + + frame->sp = fp + 0x10; + /* FP to previous frame (X29) */ + frame->fp = *(uint64_t *)(fp); + /* LR (X30) */ + frame->pc = *(uint64_t *)(fp + 8) - 4; + + return (0); +} diff --git a/sys/arm64/arm64/vfp.c b/sys/arm64/arm64/vfp.c index 7ce59b8..5e44d5e 100644 --- a/sys/arm64/arm64/vfp.c +++ b/sys/arm64/arm64/vfp.c @@ -120,7 +120,7 @@ vfp_save_state(struct thread *td) td->td_pcb->pcb_fpcr = fpcr; td->td_pcb->pcb_fpsr = fpsr; - dsb(); + dsb(ish); vfp_disable(); } critical_exit(); diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 8e20d60..4eae4df 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -95,3 +95,4 @@ device psci # Support for ARM PSCI device bpf # Berkeley packet filter options FDT +device acpi diff --git a/sys/arm64/include/acpica_machdep.h b/sys/arm64/include/acpica_machdep.h new file mode 100644 index 0000000..9a3434a --- /dev/null +++ b/sys/arm64/include/acpica_machdep.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2002 Mitsuru IWASAKI + * 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$ + */ + +/****************************************************************************** + * + * Name: acpica_machdep.h - arch-specific defines, etc. + * $Revision$ + * + *****************************************************************************/ + +#ifndef __ACPICA_MACHDEP_H__ +#define __ACPICA_MACHDEP_H__ + + +#ifdef _KERNEL + +/* Only use the reduced hardware model */ +#define ACPI_REDUCED_HARDWARE 1 + +/* Section 5.2.10.1: global lock acquire/release functions */ +int acpi_acquire_global_lock(volatile uint32_t *); +int acpi_release_global_lock(volatile uint32_t *); + +void *acpi_map_table(vm_paddr_t pa, const char *sig); +void acpi_unmap_table(void *table); +vm_paddr_t acpi_find_table(const char *sig); + +#endif /* _KERNEL */ + +#endif /* __ACPICA_MACHDEP_H__ */ diff --git a/sys/arm64/include/atomic.h b/sys/arm64/include/atomic.h index f0f6c17..99252b8 100644 --- a/sys/arm64/include/atomic.h +++ b/sys/arm64/include/atomic.h @@ -29,13 +29,29 @@ #ifndef _MACHINE_ATOMIC_H_ #define _MACHINE_ATOMIC_H_ -#define isb() __asm __volatile("isb" : : : "memory") -#define dsb() __asm __volatile("dsb sy" : : : "memory") -#define dmb() __asm __volatile("dmb sy" : : : "memory") +#define isb() __asm __volatile("isb" : : : "memory") -#define mb() dmb() -#define wmb() dmb() -#define rmb() dmb() +/* + * Options for DMB and DSB: + * oshld Outer Shareable, load + * oshst Outer Shareable, store + * osh Outer Shareable, all + * nshld Non-shareable, load + * nshst Non-shareable, store + * nsh Non-shareable, all + * ishld Inner Shareable, load + * ishst Inner Shareable, store + * ish Inner Shareable, all + * ld Full system, load + * st Full system, store + * sy Full system, all + */ +#define dsb(opt) __asm __volatile("dsb " __STRING(opt) : : : "memory") +#define dmb(opt) __asm __volatile("dmb " __STRING(opt) : : : "memory") + +#define mb() dmb(sy) /* Full system memory barrier all */ +#define wmb() dmb(st) /* Full system memory barrier store */ +#define rmb() dmb(ld) /* Full system memory barrier load */ static __inline void atomic_add_32(volatile uint32_t *p, uint32_t val) diff --git a/sys/arm64/include/iodev.h b/sys/arm64/include/iodev.h new file mode 100644 index 0000000..5521ff7 --- /dev/null +++ b/sys/arm64/include/iodev.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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 _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ + +#define iodev_read_1(a) \ +({ \ + uint8_t val; \ + __asm __volatile("ldrb %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_read_2(a) \ +({ \ + uint16_t val; \ + __asm __volatile("ldrh %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_read_4(a) \ +({ \ + uint32_t val; \ + __asm __volatile("ldr %w0, [%1]" : "=&r" (val) : "r"(a)); \ + val; \ +}) + +#define iodev_write_1(a, v) \ + __asm __volatile("strb %w0, [%1]" :: "r" (v), "r"(a)) + +#define iodev_write_2(a, v) \ + __asm __volatile("strh %w0, [%1]" :: "r" (v), "r"(a)) + +#define iodev_write_4(a, v) \ + __asm __volatile("str %w0, [%1]" :: "r" (v), "r"(a)) + +#endif /* _MACHINE_IODEV_H_ */ diff --git a/sys/arm64/include/pci_cfgreg.h b/sys/arm64/include/pci_cfgreg.h new file mode 100644 index 0000000..da23dbe --- /dev/null +++ b/sys/arm64/include/pci_cfgreg.h @@ -0,0 +1 @@ +/* $FreeBSD$ */ diff --git a/sys/arm64/include/pcpu.h b/sys/arm64/include/pcpu.h index 6de3e89..19cd758 100644 --- a/sys/arm64/include/pcpu.h +++ b/sys/arm64/include/pcpu.h @@ -36,7 +36,8 @@ #define ALT_STACK_SIZE 128 #define PCPU_MD_FIELDS \ - char __pad[129] + u_int pc_acpi_id; /* ACPI CPU id */ \ + char __pad[125] #ifdef _KERNEL diff --git a/sys/arm64/include/stack.h b/sys/arm64/include/stack.h index 8131ce5..db0d4ab 100644 --- a/sys/arm64/include/stack.h +++ b/sys/arm64/include/stack.h @@ -32,4 +32,12 @@ #define INKERNEL(va) \ ((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS) +struct unwind_state { + uint64_t fp; + uint64_t sp; + uint64_t pc; +}; + +int unwind_frame(struct unwind_state *); + #endif /* !_MACHINE_STACK_H_ */ diff --git a/sys/boot/Makefile b/sys/boot/Makefile index 2aa76b7..2607651 100644 --- a/sys/boot/Makefile +++ b/sys/boot/Makefile @@ -8,6 +8,8 @@ SUBDIR+= ficl SUBDIR+= forth .endif +SUBDIR+= common + .include <bsd.arch.inc.mk> # Pick the machine-dependent subdir based on the target architecture. diff --git a/sys/boot/common/Makefile b/sys/boot/common/Makefile new file mode 100644 index 0000000..fcca328 --- /dev/null +++ b/sys/boot/common/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.include <src.opts.mk> + +MAN+= loader.8 +.if ${MK_ZFS} != "no" +MAN+= zfsloader.8 +.endif + +.include <bsd.prog.mk> diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc index 54e8617..d647fe3 100644 --- a/sys/boot/common/Makefile.inc +++ b/sys/boot/common/Makefile.inc @@ -68,8 +68,3 @@ CFLAGS+= -DBOOT_PROMPT_123 SRCS+= install.c CFLAGS+=-I${.CURDIR}/../../../../lib/libstand .endif - -MAN+= loader.8 -.if ${MK_ZFS} != "no" -MAN+= zfsloader.8 -.endif diff --git a/sys/boot/efi/libefi/Makefile.depend b/sys/boot/efi/libefi/Makefile.depend new file mode 100644 index 0000000..c77da59 --- /dev/null +++ b/sys/boot/efi/libefi/Makefile.depend @@ -0,0 +1,17 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + include \ + include/xlocale \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/efi/loader/arch/arm64/exec.c b/sys/boot/efi/loader/arch/arm64/exec.c index 1f72269..d13e97b 100644 --- a/sys/boot/efi/loader/arch/arm64/exec.c +++ b/sys/boot/efi/loader/arch/arm64/exec.c @@ -42,6 +42,15 @@ __FBSDID("$FreeBSD$"); #include "loader_efi.h" #include "cache.h" +#include "platform/acfreebsd.h" +#include "acconfig.h" +#define ACPI_SYSTEM_XFACE +#include "actypes.h" +#include "actbl.h" + +static EFI_GUID acpi_guid = ACPI_TABLE_GUID; +static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; + static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); @@ -64,12 +73,41 @@ elf64_exec(struct preloaded_file *fp) vm_offset_t clean_addr; size_t clean_size; struct file_metadata *md; + ACPI_TABLE_RSDP *rsdp; EFI_STATUS status; EFI_PHYSICAL_ADDRESS addr; Elf_Ehdr *ehdr; - int err; + char buf[24]; + int err, revision; void (*entry)(vm_offset_t); + rsdp = efi_get_table(&acpi20_guid); + if (rsdp == NULL) { + rsdp = efi_get_table(&acpi_guid); + } + if (rsdp != NULL) { + sprintf(buf, "0x%016llx", (unsigned long long)rsdp); + setenv("hint.acpi.0.rsdp", buf, 1); + revision = rsdp->Revision; + if (revision == 0) + revision = 1; + sprintf(buf, "%d", revision); + setenv("hint.acpi.0.revision", buf, 1); + strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); + buf[sizeof(rsdp->OemId)] = '\0'; + setenv("hint.acpi.0.oem", buf, 1); + sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); + setenv("hint.acpi.0.rsdt", buf, 1); + if (revision >= 2) { + /* XXX extended checksum? */ + sprintf(buf, "0x%016llx", + (unsigned long long)rsdp->XsdtPhysicalAddress); + setenv("hint.acpi.0.xsdt", buf, 1); + sprintf(buf, "%d", rsdp->Length); + setenv("hint.acpi.0.xsdt_length", buf, 1); + } + } + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); diff --git a/sys/boot/fdt/dts/arm/beaglebone-black.dts b/sys/boot/fdt/dts/arm/beaglebone-black.dts index f5144dd..21cbf83 100644 --- a/sys/boot/fdt/dts/arm/beaglebone-black.dts +++ b/sys/boot/fdt/dts/arm/beaglebone-black.dts @@ -29,3 +29,25 @@ #include "am335x-boneblack.dts" #include "beaglebone-common.dtsi" + +&i2c0 { + tda998x: hdmi-encoder { + compatible = "nxp,tda998x"; + reg = <0x70>; + + pinctrl-names = "default", "off"; + pinctrl-0 = <&nxp_hdmi_bonelt_pins>; + pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; + status = "okay"; + }; +}; + +&lcdc { + hdmi = <&tda998x>; +}; + +/ { + hdmi { + status = "disabled"; + }; +}; diff --git a/sys/boot/ficl/Makefile.depend b/sys/boot/ficl/Makefile.depend new file mode 100644 index 0000000..ab9c549 --- /dev/null +++ b/sys/boot/ficl/Makefile.depend @@ -0,0 +1,21 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + include \ + include/xlocale \ + lib/libstand \ + lib/msun \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +softcore.o: softcore.c +softcore.po: softcore.c +.endif diff --git a/sys/boot/i386/boot0/Makefile.depend b/sys/boot/i386/boot0/Makefile.depend new file mode 100644 index 0000000..3af2d7f --- /dev/null +++ b/sys/boot/i386/boot0/Makefile.depend @@ -0,0 +1,15 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/i386/boot0sio/Makefile.depend b/sys/boot/i386/boot0sio/Makefile.depend new file mode 100644 index 0000000..3af2d7f --- /dev/null +++ b/sys/boot/i386/boot0sio/Makefile.depend @@ -0,0 +1,15 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/i386/boot2/Makefile.depend b/sys/boot/i386/boot2/Makefile.depend new file mode 100644 index 0000000..3af2d7f --- /dev/null +++ b/sys/boot/i386/boot2/Makefile.depend @@ -0,0 +1,15 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile index 6e735a4..ade6054 100644 --- a/sys/boot/i386/loader/Makefile +++ b/sys/boot/i386/loader/Makefile @@ -5,6 +5,7 @@ MK_SSP= no LOADER?= loader PROG= ${LOADER}.sym +MAN= INTERNALPROG= NEWVERSWHAT?= "bootstrap loader" x86 diff --git a/sys/boot/i386/loader/Makefile.depend b/sys/boot/i386/loader/Makefile.depend new file mode 100644 index 0000000..3af2d7f --- /dev/null +++ b/sys/boot/i386/loader/Makefile.depend @@ -0,0 +1,15 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/i386/zfsloader/Makefile.depend b/sys/boot/i386/zfsloader/Makefile.depend new file mode 100644 index 0000000..3af2d7f --- /dev/null +++ b/sys/boot/i386/zfsloader/Makefile.depend @@ -0,0 +1,15 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} + +DEP_MACHINE := ${.PARSEFILE:E} + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sys/boot/mips/beri/loader/Makefile b/sys/boot/mips/beri/loader/Makefile index d4292cc..a134f3d 100644 --- a/sys/boot/mips/beri/loader/Makefile +++ b/sys/boot/mips/beri/loader/Makefile @@ -31,6 +31,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= PROG?= loader NEWVERSWHAT= "BERI loader" ${MACHINE_CPUARCH} diff --git a/sys/boot/pc98/loader/Makefile b/sys/boot/pc98/loader/Makefile index a001c20..9333f3c 100644 --- a/sys/boot/pc98/loader/Makefile +++ b/sys/boot/pc98/loader/Makefile @@ -2,6 +2,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= LOADER?= loader PROG= ${LOADER}.sym diff --git a/sys/boot/powerpc/kboot/Makefile b/sys/boot/powerpc/kboot/Makefile index 0ca7d20..4601f29 100644 --- a/sys/boot/powerpc/kboot/Makefile +++ b/sys/boot/powerpc/kboot/Makefile @@ -2,6 +2,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= PROG= loader.kboot NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH} diff --git a/sys/boot/powerpc/ofw/Makefile b/sys/boot/powerpc/ofw/Makefile index 65b79ea..6a2fc70 100644 --- a/sys/boot/powerpc/ofw/Makefile +++ b/sys/boot/powerpc/ofw/Makefile @@ -2,6 +2,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= PROG= loader NEWVERSWHAT= "Open Firmware loader" ${MACHINE_ARCH} diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile index 3bb9cb3..861872f 100644 --- a/sys/boot/powerpc/ps3/Makefile +++ b/sys/boot/powerpc/ps3/Makefile @@ -2,6 +2,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= PROG= loader.ps3 NEWVERSWHAT= "Playstation 3 loader" ${MACHINE_ARCH} diff --git a/sys/boot/sparc64/loader/Makefile b/sys/boot/sparc64/loader/Makefile index ca2853c..5c9bfbb 100644 --- a/sys/boot/sparc64/loader/Makefile +++ b/sys/boot/sparc64/loader/Makefile @@ -2,6 +2,7 @@ .include <src.opts.mk> MK_SSP= no +MAN= PROG?= loader NEWVERSWHAT?= "bootstrap loader" sparc64 diff --git a/sys/boot/uboot/lib/copy.c b/sys/boot/uboot/lib/copy.c index bb658e3..51416ac 100644 --- a/sys/boot/uboot/lib/copy.c +++ b/sys/boot/uboot/lib/copy.c @@ -118,6 +118,13 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr) this_block = eubldr; this_size = eblock - eubldr; } + } else if (subldr < sblock && eubldr < eblock) { + /* Loader is below or engulfs the sblock */ + this_block = (eubldr < sblock) ? sblock : eubldr; + this_size = eblock - this_block; + } else { + this_block = 0; + this_size = 0; } if (biggest_size < this_size) { biggest_block = this_block; diff --git a/sys/boot/uboot/lib/glue.c b/sys/boot/uboot/lib/glue.c index d01e33b..32c4df2 100644 --- a/sys/boot/uboot/lib/glue.c +++ b/sys/boot/uboot/lib/glue.c @@ -513,7 +513,7 @@ ub_env_enum(const char *last) if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) return (NULL); - if (env == NULL) + if (env == NULL || last == env) /* no more env. variables to enumerate */ return (NULL); diff --git a/sys/cam/cam.c b/sys/cam/cam.c index 939dd76..1f627ef 100644 --- a/sys/cam/cam.c +++ b/sys/cam/cam.c @@ -157,6 +157,56 @@ cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen) *dst = '\0'; } +void +cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen, + uint32_t flags) +{ + + /* Trim leading/trailing spaces, nulls. */ + while (srclen > 0 && src[0] == ' ') + src++, srclen--; + while (srclen > 0 + && (src[srclen-1] == ' ' || src[srclen-1] == '\0')) + srclen--; + + while (srclen > 0) { + if (*src < 0x20 || *src >= 0x80) { + /* SCSI-II Specifies that these should never occur. */ + /* non-printable character */ + switch (flags & CAM_STRVIS_FLAG_NONASCII_MASK) { + case CAM_STRVIS_FLAG_NONASCII_ESC: + sbuf_printf(sb, "\\%c%c%c", + ((*src & 0300) >> 6) + '0', + ((*src & 0070) >> 3) + '0', + ((*src & 0007) >> 0) + '0'); + break; + case CAM_STRVIS_FLAG_NONASCII_RAW: + /* + * If we run into a NUL, just transform it + * into a space. + */ + if (*src != 0x00) + sbuf_putc(sb, *src); + else + sbuf_putc(sb, ' '); + break; + case CAM_STRVIS_FLAG_NONASCII_SPC: + sbuf_putc(sb, ' '); + break; + case CAM_STRVIS_FLAG_NONASCII_TRIM: + default: + break; + } + } else { + /* normal character */ + sbuf_putc(sb, *src); + } + src++; + srclen--; + } +} + + /* * Compare string with pattern, returning 0 on match. * Short pattern matches trailing blanks in name, diff --git a/sys/cam/cam.h b/sys/cam/cam.h index e08524b..63f83c7 100644 --- a/sys/cam/cam.h +++ b/sys/cam/cam.h @@ -342,6 +342,15 @@ typedef enum { CAM_EAF_PRINT_RESULT = 0x20 } cam_error_ata_flags; +typedef enum { + CAM_STRVIS_FLAG_NONE = 0x00, + CAM_STRVIS_FLAG_NONASCII_MASK = 0x03, + CAM_STRVIS_FLAG_NONASCII_TRIM = 0x00, + CAM_STRVIS_FLAG_NONASCII_RAW = 0x01, + CAM_STRVIS_FLAG_NONASCII_SPC = 0x02, + CAM_STRVIS_FLAG_NONASCII_ESC = 0x03 +} cam_strvis_flags; + struct cam_status_entry { cam_status status_code; @@ -354,6 +363,7 @@ extern const int num_cam_status_entries; extern int cam_sort_io_queues; #endif union ccb; +struct sbuf; #ifdef SYSCTL_DECL /* from sysctl.h */ SYSCTL_DECL(_kern_cam); @@ -366,6 +376,8 @@ caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, int entry_size, cam_quirkmatch_t *comp_func); void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen); +void cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen, + uint32_t flags); int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len); const struct cam_status_entry* diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 6276774..3d562d0 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -383,8 +383,8 @@ static int ctl_open(struct cdev *dev, int flags, int fmt, struct thread *td); static int ctl_close(struct cdev *dev, int flags, int fmt, struct thread *td); static void ctl_ioctl_online(void *arg); static void ctl_ioctl_offline(void *arg); -static int ctl_ioctl_lun_enable(void *arg, struct ctl_id targ_id, int lun_id); -static int ctl_ioctl_lun_disable(void *arg, struct ctl_id targ_id, int lun_id); +static int ctl_ioctl_lun_enable(void *arg, int lun_id); +static int ctl_ioctl_lun_disable(void *arg, int lun_id); static int ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio); static int ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio); static int ctl_ioctl_submit_wait(union ctl_io *io); @@ -399,7 +399,7 @@ static int ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num, static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td); static int ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *lun, - struct ctl_be_lun *be_lun, struct ctl_id target_id); + struct ctl_be_lun *be_lun); static int ctl_free_lun(struct ctl_lun *lun); static void ctl_create_lun(struct ctl_be_lun *be_lun); static struct ctl_port * ctl_io_port(struct ctl_io_hdr *io_hdr); @@ -1128,13 +1128,6 @@ ctl_init(void) softc->port_offset = (softc->ha_id - 1) * CTL_MAX_PORTS; softc->persis_offset = softc->port_offset * CTL_MAX_INIT_PER_PORT; - /* - * XXX KDM need to figure out where we want to get our target ID - * and WWID. Is it different on each port? - */ - softc->target.id = 0; - softc->target.wwid[0] = 0x12345678; - softc->target.wwid[1] = 0x87654321; STAILQ_INIT(&softc->lun_list); STAILQ_INIT(&softc->pending_lun_queue); STAILQ_INIT(&softc->fe_list); @@ -1647,13 +1640,13 @@ ctl_create_iid(struct ctl_port *port, int iid, uint8_t *buf) } static int -ctl_ioctl_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) +ctl_ioctl_lun_enable(void *arg, int lun_id) { return (0); } static int -ctl_ioctl_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) +ctl_ioctl_lun_disable(void *arg, int lun_id) { return (0); } @@ -2478,28 +2471,9 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, mtx_unlock(&softc->ctl_lock); if (cmd == CTL_ENABLE_PORT) { - struct ctl_lun *lun; - - STAILQ_FOREACH(lun, &softc->lun_list, - links) { - port->lun_enable(port->targ_lun_arg, - lun->target, - lun->lun); - } - ctl_port_online(port); } else if (cmd == CTL_DISABLE_PORT) { - struct ctl_lun *lun; - ctl_port_offline(port); - - STAILQ_FOREACH(lun, &softc->lun_list, - links) { - port->lun_disable( - port->targ_lun_arg, - lun->target, - lun->lun); - } } mtx_lock(&softc->ctl_lock); @@ -3560,26 +3534,22 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, mtx_unlock(&softc->ctl_lock); return (ENXIO); } + mtx_unlock(&softc->ctl_lock); // XXX: port_enable sleeps if (lm->plun < CTL_MAX_LUNS) { if (lm->lun == UINT32_MAX) retval = ctl_lun_map_unset(port, lm->plun); else if (lm->lun < CTL_MAX_LUNS && softc->ctl_luns[lm->lun] != NULL) retval = ctl_lun_map_set(port, lm->plun, lm->lun); - else { - mtx_unlock(&softc->ctl_lock); + else return (ENXIO); - } } else if (lm->plun == UINT32_MAX) { if (lm->lun == UINT32_MAX) retval = ctl_lun_map_deinit(port); else retval = ctl_lun_map_init(port); - } else { - mtx_unlock(&softc->ctl_lock); + } else return (ENXIO); - } - mtx_unlock(&softc->ctl_lock); break; } default: { @@ -3649,6 +3619,8 @@ ctl_port_idx(int port_num) int ctl_lun_map_init(struct ctl_port *port) { + struct ctl_softc *softc = control_softc; + struct ctl_lun *lun; uint32_t i; if (port->lun_map == NULL) @@ -3658,17 +3630,27 @@ ctl_lun_map_init(struct ctl_port *port) return (ENOMEM); for (i = 0; i < CTL_MAX_LUNS; i++) port->lun_map[i] = UINT32_MAX; + if (port->status & CTL_PORT_STATUS_ONLINE) { + STAILQ_FOREACH(lun, &softc->lun_list, links) + port->lun_disable(port->targ_lun_arg, lun->lun); + } return (0); } int ctl_lun_map_deinit(struct ctl_port *port) { + struct ctl_softc *softc = control_softc; + struct ctl_lun *lun; if (port->lun_map == NULL) return (0); free(port->lun_map, M_CTL); port->lun_map = NULL; + if (port->status & CTL_PORT_STATUS_ONLINE) { + STAILQ_FOREACH(lun, &softc->lun_list, links) + port->lun_enable(port->targ_lun_arg, lun->lun); + } return (0); } @@ -3676,37 +3658,31 @@ int ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun) { int status; + uint32_t old; if (port->lun_map == NULL) { status = ctl_lun_map_init(port); if (status != 0) return (status); } + old = port->lun_map[plun]; port->lun_map[plun] = glun; + if ((port->status & CTL_PORT_STATUS_ONLINE) && old >= CTL_MAX_LUNS) + port->lun_enable(port->targ_lun_arg, plun); return (0); } int ctl_lun_map_unset(struct ctl_port *port, uint32_t plun) { + uint32_t old; if (port->lun_map == NULL) return (0); + old = port->lun_map[plun]; port->lun_map[plun] = UINT32_MAX; - return (0); -} - -int -ctl_lun_map_unsetg(struct ctl_port *port, uint32_t glun) -{ - int i; - - if (port->lun_map == NULL) - return (0); - for (i = 0; i < CTL_MAX_LUNS; i++) { - if (port->lun_map[i] == glun) - port->lun_map[i] = UINT32_MAX; - } + if ((port->status & CTL_PORT_STATUS_ONLINE) && old < CTL_MAX_LUNS) + port->lun_disable(port->targ_lun_arg, plun); return (0); } @@ -4532,10 +4508,9 @@ hex2bin(const char *str, uint8_t *buf, int buf_size) */ static int ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, - struct ctl_be_lun *const be_lun, struct ctl_id target_id) + struct ctl_be_lun *const be_lun) { struct ctl_lun *nlun, *lun; - struct ctl_port *port; struct scsi_vpd_id_descriptor *desc; struct scsi_vpd_id_t10 *t10id; const char *eui, *naa, *scsiname, *vendor, *value; @@ -4670,8 +4645,7 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, lun_number = ctl_ffz(ctl_softc->ctl_lun_mask, CTL_MAX_LUNS); if (lun_number == -1) { mtx_unlock(&ctl_softc->ctl_lock); - printf("ctl: can't allocate LUN on target %ju, out of " - "LUNs\n", (uintmax_t)target_id.id); + printf("ctl: can't allocate LUN, out of LUNs\n"); if (lun->flags & CTL_LUN_MALLOCED) free(lun, M_CTL); be_lun->lun_config_status(be_lun->be_lun, @@ -4682,7 +4656,6 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, ctl_set_mask(ctl_softc->ctl_lun_mask, lun_number); mtx_init(&lun->lun_lock, "CTL LUN", NULL, MTX_DEF); - lun->target = target_id; lun->lun = lun_number; lun->be_lun = be_lun; /* @@ -4765,24 +4738,6 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, mtx_unlock(&ctl_softc->ctl_lock); lun->be_lun->lun_config_status(lun->be_lun->be_lun, CTL_LUN_CONFIG_OK); - - /* - * Run through each registered FETD and bring it online if it isn't - * already. Enable the target ID if it hasn't been enabled, and - * enable this particular LUN. - */ - STAILQ_FOREACH(port, &ctl_softc->port_list, links) { - int retval; - - retval = port->lun_enable(port->targ_lun_arg, target_id,lun_number); - if (retval != 0) { - printf("ctl_alloc_lun: FETD %s port %d returned error " - "%d for lun_enable on target %ju lun %d\n", - port->port_name, port->targ_port, retval, - (uintmax_t)target_id.id, lun_number); - } else - port->status |= CTL_PORT_STATUS_LUN_ONLINE; - } return (0); } @@ -4796,7 +4751,6 @@ static int ctl_free_lun(struct ctl_lun *lun) { struct ctl_softc *softc; - struct ctl_port *port; struct ctl_lun *nlun; int i; @@ -4804,9 +4758,6 @@ ctl_free_lun(struct ctl_lun *lun) mtx_assert(&softc->ctl_lock, MA_OWNED); - STAILQ_FOREACH(port, &softc->port_list, links) - ctl_lun_map_unsetg(port, lun->lun); - STAILQ_REMOVE(&softc->lun_list, lun, ctl_lun, links); ctl_clear_mask(softc->ctl_lun_mask, lun->lun); @@ -4819,58 +4770,6 @@ ctl_free_lun(struct ctl_lun *lun) softc->num_luns--; /* - * XXX KDM this scheme only works for a single target/multiple LUN - * setup. It needs to be revamped for a multiple target scheme. - * - * XXX KDM this results in port->lun_disable() getting called twice, - * once when ctl_disable_lun() is called, and a second time here. - * We really need to re-think the LUN disable semantics. There - * should probably be several steps/levels to LUN removal: - * - disable - * - invalidate - * - free - * - * Right now we only have a disable method when communicating to - * the front end ports, at least for individual LUNs. - */ -#if 0 - STAILQ_FOREACH(port, &softc->port_list, links) { - int retval; - - retval = port->lun_disable(port->targ_lun_arg, lun->target, - lun->lun); - if (retval != 0) { - printf("ctl_free_lun: FETD %s port %d returned error " - "%d for lun_disable on target %ju lun %jd\n", - port->port_name, port->targ_port, retval, - (uintmax_t)lun->target.id, (intmax_t)lun->lun); - } - - if (STAILQ_FIRST(&softc->lun_list) == NULL) { - port->status &= ~CTL_PORT_STATUS_LUN_ONLINE; - - retval = port->targ_disable(port->targ_lun_arg,lun->target); - if (retval != 0) { - printf("ctl_free_lun: FETD %s port %d " - "returned error %d for targ_disable on " - "target %ju\n", port->port_name, - port->targ_port, retval, - (uintmax_t)lun->target.id); - } else - port->status &= ~CTL_PORT_STATUS_TARG_ONLINE; - - if ((port->status & CTL_PORT_STATUS_TARG_ONLINE) != 0) - continue; - -#if 0 - port->port_offline(port->onoff_arg); - port->status &= ~CTL_PORT_STATUS_ONLINE; -#endif - } - } -#endif - - /* * Tell the backend to free resources, if this LUN has a backend. */ atomic_subtract_int(&lun->be_lun->be->num_luns, 1); @@ -4906,7 +4805,7 @@ ctl_create_lun(struct ctl_be_lun *be_lun) /* * ctl_alloc_lun() should handle all potential failure cases. */ - ctl_alloc_lun(softc, NULL, be_lun, softc->target); + ctl_alloc_lun(softc, NULL, be_lun); } int @@ -4949,6 +4848,9 @@ ctl_enable_lun(struct ctl_be_lun *be_lun) for (port = STAILQ_FIRST(&softc->port_list); port != NULL; port = nport) { nport = STAILQ_NEXT(port, links); + if ((port->status & CTL_PORT_STATUS_ONLINE) == 0 || + port->lun_map != NULL) + continue; /* * Drop the lock while we call the FETD's enable routine. @@ -4956,20 +4858,14 @@ ctl_enable_lun(struct ctl_be_lun *be_lun) * case of the internal initiator frontend. */ mtx_unlock(&softc->ctl_lock); - retval = port->lun_enable(port->targ_lun_arg, lun->target,lun->lun); + retval = port->lun_enable(port->targ_lun_arg, lun->lun); mtx_lock(&softc->ctl_lock); if (retval != 0) { printf("%s: FETD %s port %d returned error " - "%d for lun_enable on target %ju lun %jd\n", - __func__, port->port_name, port->targ_port, retval, - (uintmax_t)lun->target.id, (intmax_t)lun->lun); + "%d for lun_enable on lun %jd\n", + __func__, port->port_name, port->targ_port, + retval, (intmax_t)lun->lun); } -#if 0 - else { - /* NOTE: TODO: why does lun enable affect port status? */ - port->status |= CTL_PORT_STATUS_LUN_ONLINE; - } -#endif } mtx_unlock(&softc->ctl_lock); @@ -4999,6 +4895,9 @@ ctl_disable_lun(struct ctl_be_lun *be_lun) mtx_unlock(&lun->lun_lock); STAILQ_FOREACH(port, &softc->port_list, links) { + if ((port->status & CTL_PORT_STATUS_ONLINE) == 0 || + port->lun_map != NULL) + continue; mtx_unlock(&softc->ctl_lock); /* * Drop the lock before we call the frontend's disable @@ -5007,14 +4906,13 @@ ctl_disable_lun(struct ctl_be_lun *be_lun) * XXX KDM what happens if the frontend list changes while * we're traversing it? It's unlikely, but should be handled. */ - retval = port->lun_disable(port->targ_lun_arg, lun->target, - lun->lun); + retval = port->lun_disable(port->targ_lun_arg, lun->lun); mtx_lock(&softc->ctl_lock); if (retval != 0) { printf("%s: FETD %s port %d returned error " - "%d for lun_disable on target %ju lun %jd\n", - __func__, port->port_name, port->targ_port, retval, - (uintmax_t)lun->target.id, (intmax_t)lun->lun); + "%d for lun_disable on lun %jd\n", + __func__, port->port_name, port->targ_port, + retval, (intmax_t)lun->lun); } } @@ -9450,11 +9348,16 @@ ctl_report_luns(struct ctl_scsiio *ctsio) well_known = 0; cdb = (struct scsi_report_luns *)ctsio->cdb; + port = ctl_io_port(&ctsio->io_hdr); CTL_DEBUG_PRINT(("ctl_report_luns\n")); mtx_lock(&softc->ctl_lock); - num_luns = softc->num_luns; + num_luns = 0; + for (targ_lun_id = 0; targ_lun_id < CTL_MAX_LUNS; targ_lun_id++) { + if (ctl_lun_map_from_port(port, targ_lun_id) < CTL_MAX_LUNS) + num_luns++; + } mtx_unlock(&softc->ctl_lock); switch (cdb->select_report) { @@ -9497,7 +9400,6 @@ ctl_report_luns(struct ctl_scsiio *ctsio) request_lun = (struct ctl_lun *) ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; - port = ctl_io_port(&ctsio->io_hdr); lun_datalen = sizeof(*lun_data) + (num_luns * sizeof(struct scsi_report_luns_lundata)); diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c index c38e527..e22b9d4 100644 --- a/sys/cam/ctl/ctl_frontend.c +++ b/sys/cam/ctl/ctl_frontend.c @@ -301,6 +301,20 @@ ctl_port_set_wwns(struct ctl_port *port, int wwnn_valid, uint64_t wwnn, void ctl_port_online(struct ctl_port *port) { + struct ctl_softc *softc = control_softc; + struct ctl_lun *lun; + uint32_t l; + + if (port->lun_map) { + for (l = 0; l < CTL_MAX_LUNS; l++) { + if (ctl_lun_map_from_port(port, l) >= CTL_MAX_LUNS) + continue; + port->lun_enable(port->targ_lun_arg, l); + } + } else { + STAILQ_FOREACH(lun, &softc->lun_list, links) + port->lun_enable(port->targ_lun_arg, lun->lun); + } port->port_online(port->onoff_arg); /* XXX KDM need a lock here? */ port->status |= CTL_PORT_STATUS_ONLINE; @@ -309,7 +323,21 @@ ctl_port_online(struct ctl_port *port) void ctl_port_offline(struct ctl_port *port) { + struct ctl_softc *softc = control_softc; + struct ctl_lun *lun; + uint32_t l; + port->port_offline(port->onoff_arg); + if (port->lun_map) { + for (l = 0; l < CTL_MAX_LUNS; l++) { + if (ctl_lun_map_from_port(port, l) >= CTL_MAX_LUNS) + continue; + port->lun_disable(port->targ_lun_arg, l); + } + } else { + STAILQ_FOREACH(lun, &softc->lun_list, links) + port->lun_disable(port->targ_lun_arg, lun->lun); + } /* XXX KDM need a lock here? */ port->status &= ~CTL_PORT_STATUS_ONLINE; } diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h index f1cc1c4..470d7a7 100644 --- a/sys/cam/ctl/ctl_frontend.h +++ b/sys/cam/ctl/ctl_frontend.h @@ -41,16 +41,14 @@ typedef enum { CTL_PORT_STATUS_NONE = 0x00, - CTL_PORT_STATUS_ONLINE = 0x01, - CTL_PORT_STATUS_TARG_ONLINE = 0x02, - CTL_PORT_STATUS_LUN_ONLINE = 0x04 + CTL_PORT_STATUS_ONLINE = 0x01 } ctl_port_status; typedef int (*fe_init_t)(void); typedef void (*fe_shutdown_t)(void); typedef void (*port_func_t)(void *onoff_arg); typedef int (*port_info_func_t)(void *onoff_arg, struct sbuf *sb); -typedef int (*lun_func_t)(void *arg, struct ctl_id targ_id, int lun_id); +typedef int (*lun_func_t)(void *arg, int lun_id); typedef int (*fe_ioctl_t)(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td); diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c index e779e48..3abc572 100644 --- a/sys/cam/ctl/ctl_frontend_cam_sim.c +++ b/sys/cam/ctl/ctl_frontend_cam_sim.c @@ -99,8 +99,8 @@ int cfcs_init(void); static void cfcs_poll(struct cam_sim *sim); static void cfcs_online(void *arg); static void cfcs_offline(void *arg); -static int cfcs_lun_enable(void *arg, struct ctl_id target_id, int lun_id); -static int cfcs_lun_disable(void *arg, struct ctl_id target_id, int lun_id); +static int cfcs_lun_enable(void *arg, int lun_id); +static int cfcs_lun_disable(void *arg, int lun_id); static void cfcs_datamove(union ctl_io *io); static void cfcs_done(union ctl_io *io); void cfcs_action(struct cam_sim *sim, union ccb *ccb); @@ -303,12 +303,12 @@ cfcs_offline(void *arg) } static int -cfcs_lun_enable(void *arg, struct ctl_id target_id, int lun_id) +cfcs_lun_enable(void *arg, int lun_id) { return (0); } static int -cfcs_lun_disable(void *arg, struct ctl_id target_id, int lun_id) +cfcs_lun_disable(void *arg, int lun_id) { return (0); } diff --git a/sys/cam/ctl/ctl_frontend_internal.c b/sys/cam/ctl/ctl_frontend_internal.c index 23bd0cf..4768292 100644 --- a/sys/cam/ctl/ctl_frontend_internal.c +++ b/sys/cam/ctl/ctl_frontend_internal.c @@ -144,7 +144,6 @@ typedef enum { } cfi_lun_state; struct cfi_lun { - struct ctl_id target_id; int lun_id; struct scsi_inquiry_data inq_data; uint64_t num_blocks; @@ -192,8 +191,8 @@ int cfi_init(void); void cfi_shutdown(void) __unused; static void cfi_online(void *arg); static void cfi_offline(void *arg); -static int cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id); -static int cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id); +static int cfi_lun_enable(void *arg, int lun_id); +static int cfi_lun_disable(void *arg, int lun_id); static void cfi_datamove(union ctl_io *io); static cfi_error_action cfi_checkcond_parse(union ctl_io *io, struct cfi_lun_io *lun_io); @@ -324,7 +323,7 @@ cfi_offline(void *arg) } static int -cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) +cfi_lun_enable(void *arg, int lun_id) { struct cfi_softc *softc; struct cfi_lun *lun; @@ -335,8 +334,7 @@ cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) found = 0; mtx_lock(&softc->lock); STAILQ_FOREACH(lun, &softc->lun_list, links) { - if ((lun->target_id.id == target_id.id) - && (lun->lun_id == lun_id)) { + if (lun->lun_id == lun_id) { found = 1; break; } @@ -356,7 +354,6 @@ cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) return (1); } - lun->target_id = target_id; lun->lun_id = lun_id; lun->cur_tag_num = 0; lun->state = CFI_LUN_INQUIRY; @@ -373,7 +370,7 @@ cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) } static int -cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id) +cfi_lun_disable(void *arg, int lun_id) { struct cfi_softc *softc; struct cfi_lun *lun; @@ -391,8 +388,7 @@ cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id) */ mtx_lock(&softc->lock); STAILQ_FOREACH(lun, &softc->lun_list, links) { - if ((lun->target_id.id == target_id.id) - && (lun->lun_id == lun_id)) { + if (lun->lun_id == lun_id) { found = 1; break; } @@ -403,8 +399,7 @@ cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id) mtx_unlock(&softc->lock); if (found == 0) { - printf("%s: can't find target %ju lun %d\n", __func__, - (uintmax_t)target_id.id, lun_id); + printf("%s: can't find lun %d\n", __func__, lun_id); return (1); } @@ -700,7 +695,7 @@ cfi_init_io(union ctl_io *io, struct cfi_lun *lun, io->io_hdr.nexus.initid.id = 7; io->io_hdr.nexus.targ_port = lun->softc->port.targ_port; - io->io_hdr.nexus.targ_target.id = lun->target_id.id; + io->io_hdr.nexus.targ_target.id = 0; io->io_hdr.nexus.targ_lun = lun->lun_id; io->io_hdr.retries = retries; lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; @@ -1008,8 +1003,7 @@ cfi_lun_probe(struct cfi_lun *lun, int have_lock) M_CTL_CFI, M_NOWAIT); if (dataptr == NULL) { printf("%s: unable to allocate SCSI read capacity " - "buffer for target %ju lun %d\n", __func__, - (uintmax_t)lun->target_id.id, lun->lun_id); + "buffer for lun %d\n", __func__, lun->lun_id); return; } if (lun->state == CFI_LUN_READCAPACITY) { diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index 2742c3d..652c961 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -147,10 +147,8 @@ int cfiscsi_init(void); static void cfiscsi_online(void *arg); static void cfiscsi_offline(void *arg); static int cfiscsi_info(void *arg, struct sbuf *sb); -static int cfiscsi_lun_enable(void *arg, - struct ctl_id target_id, int lun_id); -static int cfiscsi_lun_disable(void *arg, - struct ctl_id target_id, int lun_id); +static int cfiscsi_lun_enable(void *arg, int lun_id); +static int cfiscsi_lun_disable(void *arg, int lun_id); static int cfiscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td); static void cfiscsi_datamove(union ctl_io *io); @@ -2373,14 +2371,14 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name, } static int -cfiscsi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) +cfiscsi_lun_enable(void *arg, int lun_id) { return (0); } static int -cfiscsi_lun_disable(void *arg, struct ctl_id target_id, int lun_id) +cfiscsi_lun_disable(void *arg, int lun_id) { return (0); diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 428142c..8a00b5c 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -397,7 +397,6 @@ struct ctl_devid { struct tpc_list; struct ctl_lun { struct mtx lun_lock; - struct ctl_id target; uint64_t lun; ctl_lun_flags flags; ctl_lun_serseq serseq; @@ -460,7 +459,6 @@ struct ctl_softc { struct mtx ctl_lock; struct cdev *dev; int open_count; - struct ctl_id target; int num_disks; int num_luns; ctl_gen_flags flags; @@ -494,6 +492,7 @@ struct ctl_softc { struct ctl_thread threads[CTL_MAX_THREADS]; TAILQ_HEAD(tpc_tokens, tpc_token) tpc_tokens; struct callout tpc_timeout; + struct mtx tpc_lock; }; #ifdef _KERNEL @@ -507,7 +506,6 @@ int ctl_lun_map_init(struct ctl_port *port); int ctl_lun_map_deinit(struct ctl_port *port); int ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun); int ctl_lun_map_unset(struct ctl_port *port, uint32_t plun); -int ctl_lun_map_unsetg(struct ctl_port *port, uint32_t glun); uint32_t ctl_lun_map_from_port(struct ctl_port *port, uint32_t plun); uint32_t ctl_lun_map_to_port(struct ctl_port *port, uint32_t glun); int ctl_pool_create(struct ctl_softc *ctl_softc, const char *pool_name, diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c index fee5b90..490cddd 100644 --- a/sys/cam/ctl/ctl_tpc.c +++ b/sys/cam/ctl/ctl_tpc.c @@ -167,6 +167,7 @@ tpc_timeout(void *arg) } /* Free inactive ROD tokens with expired timeout. */ + mtx_lock(&softc->tpc_lock); TAILQ_FOREACH_SAFE(token, &softc->tpc_tokens, links, ttoken) { if (token->active || time_uptime < token->last_active + token->timeout + 1) @@ -175,6 +176,7 @@ tpc_timeout(void *arg) free(token->params, M_CTL); free(token, M_CTL); } + mtx_unlock(&softc->tpc_lock); callout_schedule(&softc->tpc_timeout, hz); } @@ -182,6 +184,7 @@ void ctl_tpc_init(struct ctl_softc *softc) { + mtx_init(&softc->tpc_lock, "CTL TPC mutex", NULL, MTX_DEF); TAILQ_INIT(&softc->tpc_tokens); callout_init_mtx(&softc->tpc_timeout, &softc->ctl_lock, 0); callout_reset(&softc->tpc_timeout, hz, tpc_timeout, softc); @@ -195,13 +198,14 @@ ctl_tpc_shutdown(struct ctl_softc *softc) callout_drain(&softc->tpc_timeout); /* Free ROD tokens. */ - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); while ((token = TAILQ_FIRST(&softc->tpc_tokens)) != NULL) { TAILQ_REMOVE(&softc->tpc_tokens, token, links); free(token->params, M_CTL); free(token, M_CTL); } - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); + mtx_destroy(&softc->tpc_lock); } void @@ -227,7 +231,7 @@ ctl_tpc_lun_shutdown(struct ctl_lun *lun) } /* Free ROD tokens for this LUN. */ - mtx_assert(&softc->ctl_lock, MA_OWNED); + mtx_lock(&softc->tpc_lock); TAILQ_FOREACH_SAFE(token, &softc->tpc_tokens, links, ttoken) { if (token->lun != lun->lun || token->active) continue; @@ -235,6 +239,7 @@ ctl_tpc_lun_shutdown(struct ctl_lun *lun) free(token->params, M_CTL); free(token, M_CTL); } + mtx_unlock(&softc->tpc_lock); } int @@ -1394,10 +1399,10 @@ done: free(list->params, M_CTL); list->params = NULL; if (list->token) { - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); if (--list->token->active == 0) list->token->last_active = time_uptime; - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); list->token = NULL; } mtx_lock(&lun->lun_lock); @@ -1991,9 +1996,9 @@ ctl_populate_token(struct ctl_scsiio *ctsio) list->curseg = 0; list->completed = 1; list->last_active = time_uptime; - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); TAILQ_INSERT_TAIL(&softc->tpc_tokens, token, links); - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); ctl_set_success(ctsio); ctl_done((union ctl_io *)ctsio); return (CTL_RETVAL_COMPLETE); @@ -2100,7 +2105,7 @@ ctl_write_using_token(struct ctl_scsiio *ctsio) return (CTL_RETVAL_COMPLETE); } - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); TAILQ_FOREACH(token, &softc->tpc_tokens, links) { if (memcmp(token->token, data->rod_token, sizeof(data->rod_token)) == 0) @@ -2112,7 +2117,7 @@ ctl_write_using_token(struct ctl_scsiio *ctsio) if (data->flags & EC_WUT_DEL_TKN) token->timeout = 0; } - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); if (token == NULL) { mtx_lock(&lun->lun_lock); TAILQ_REMOVE(&lun->tpc_lists, list, links); @@ -2254,10 +2259,10 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio) retval = CTL_RETVAL_COMPLETE; tokens = 0; - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); TAILQ_FOREACH(token, &softc->tpc_tokens, links) tokens++; - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); if (tokens > 512) tokens = 512; @@ -2282,7 +2287,7 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio) data = (struct scsi_report_all_rod_tokens_data *)ctsio->kern_data_ptr; i = 0; - mtx_lock(&softc->ctl_lock); + mtx_lock(&softc->tpc_lock); TAILQ_FOREACH(token, &softc->tpc_tokens, links) { if (i >= tokens) break; @@ -2290,7 +2295,7 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio) token->token, 96); i++; } - mtx_unlock(&softc->ctl_lock); + mtx_unlock(&softc->tpc_lock); scsi_ulto4b(sizeof(*data) - 4 + i * 96, data->available_data); /* printf("RART tokens=%d\n", i); diff --git a/sys/cam/ctl/ctl_tpc_local.c b/sys/cam/ctl/ctl_tpc_local.c index a8f675b..d0319ee 100644 --- a/sys/cam/ctl/ctl_tpc_local.c +++ b/sys/cam/ctl/ctl_tpc_local.c @@ -69,8 +69,8 @@ static int tpcl_init(void); static void tpcl_shutdown(void); static void tpcl_online(void *arg); static void tpcl_offline(void *arg); -static int tpcl_lun_enable(void *arg, struct ctl_id target_id, int lun_id); -static int tpcl_lun_disable(void *arg, struct ctl_id target_id, int lun_id); +static int tpcl_lun_enable(void *arg, int lun_id); +static int tpcl_lun_disable(void *arg, int lun_id); static void tpcl_datamove(union ctl_io *io); static void tpcl_done(union ctl_io *io); @@ -152,14 +152,14 @@ tpcl_offline(void *arg) } static int -tpcl_lun_enable(void *arg, struct ctl_id target_id, int lun_id) +tpcl_lun_enable(void *arg, int lun_id) { return (0); } static int -tpcl_lun_disable(void *arg, struct ctl_id target_id, int lun_id) +tpcl_lun_disable(void *arg, int lun_id) { return (0); diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 74ec3df..6bd0196 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -104,10 +104,10 @@ struct ctlfe_lun_softc { uint64_t ccbs_freed; uint64_t ctios_sent; uint64_t ctios_returned; - uint64_t atios_sent; - uint64_t atios_returned; - uint64_t inots_sent; - uint64_t inots_returned; + uint64_t atios_alloced; + uint64_t atios_freed; + uint64_t inots_alloced; + uint64_t inots_freed; /* bus_dma_tag_t dma_tag; */ TAILQ_HEAD(, ccb_hdr) work_queue; STAILQ_ENTRY(ctlfe_lun_softc) links; @@ -202,10 +202,8 @@ static void ctlfedone(struct cam_periph *periph, static void ctlfe_onoffline(void *arg, int online); static void ctlfe_online(void *arg); static void ctlfe_offline(void *arg); -static int ctlfe_lun_enable(void *arg, struct ctl_id targ_id, - int lun_id); -static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id, - int lun_id); +static int ctlfe_lun_enable(void *arg, int lun_id); +static int ctlfe_lun_disable(void *arg, int lun_id); static void ctlfe_dump_sim(struct cam_sim *sim); static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc); static void ctlfe_datamove(union ctl_io *io); @@ -546,6 +544,7 @@ ctlferegister(struct cam_periph *periph, void *arg) status = CAM_RESRC_UNAVAIL; break; } + softc->atios_alloced++; new_ccb->ccb_h.io_ptr = new_io; xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); @@ -553,7 +552,6 @@ ctlferegister(struct cam_periph *periph, void *arg) new_ccb->ccb_h.cbfcnp = ctlfedone; new_ccb->ccb_h.flags |= CAM_UNLOCKED; xpt_action(new_ccb); - softc->atios_sent++; status = new_ccb->ccb_h.status; if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { ctl_free_io(new_io); @@ -591,6 +589,7 @@ ctlferegister(struct cam_periph *periph, void *arg) status = CAM_RESRC_UNAVAIL; break; } + softc->inots_alloced++; new_ccb->ccb_h.io_ptr = new_io; xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); @@ -598,7 +597,6 @@ ctlferegister(struct cam_periph *periph, void *arg) new_ccb->ccb_h.cbfcnp = ctlfedone; new_ccb->ccb_h.flags |= CAM_UNLOCKED; xpt_action(new_ccb); - softc->inots_sent++; status = new_ccb->ccb_h.status; if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { /* @@ -650,10 +648,6 @@ ctlfeoninvalidate(struct cam_periph *periph) * XXX KDM what do we do now? */ } - xpt_print(periph->path, "LUN removed, %ju ATIOs outstanding, %ju " - "INOTs outstanding, %d refs\n", softc->atios_sent - - softc->atios_returned, softc->inots_sent - - softc->inots_returned, periph->refcount); bus_softc = softc->parent_softc; mtx_lock(&bus_softc->lun_softc_mtx); @@ -666,13 +660,20 @@ ctlfecleanup(struct cam_periph *periph) { struct ctlfe_lun_softc *softc; - xpt_print(periph->path, "%s: Called\n", __func__); - softc = (struct ctlfe_lun_softc *)periph->softc; - /* - * XXX KDM is there anything else that needs to be done here? - */ + KASSERT(softc->ccbs_freed == softc->ccbs_alloced, ("%s: " + "ccbs_freed %ju != ccbs_alloced %ju", __func__, + softc->ccbs_freed, softc->ccbs_alloced)); + KASSERT(softc->ctios_returned == softc->ctios_sent, ("%s: " + "ctios_returned %ju != ctios_sent %ju", __func__, + softc->ctios_returned, softc->ctios_sent)); + KASSERT(softc->atios_freed == softc->atios_alloced, ("%s: " + "atios_freed %ju != atios_alloced %ju", __func__, + softc->atios_freed, softc->atios_alloced)); + KASSERT(softc->inots_freed == softc->inots_alloced, ("%s: " + "inots_freed %ju != inots_alloced %ju", __func__, + softc->inots_freed, softc->inots_alloced)); free(softc, M_CTLFE); } @@ -845,15 +846,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) atio->ccb_h.target_lun = CAM_LUN_WILDCARD; } - if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { - cam_release_devq(periph->path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); - atio->ccb_h.status &= ~CAM_DEV_QFRZN; - } - if (atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) { xpt_print(periph->path, "%s: func_code " "is %#x\n", __func__, @@ -871,7 +863,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) * Send the ATIO back down to the SIM. */ xpt_action((union ccb *)atio); - softc->atios_sent++; /* * If we still have work to do, ask for @@ -964,15 +955,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) xpt_action(start_ccb); cam_periph_lock(periph); - if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { - cam_release_devq(periph->path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); - atio->ccb_h.status &= ~CAM_DEV_QFRZN; - } - /* * If we still have work to do, ask for another CCB. */ @@ -989,11 +971,11 @@ ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb) switch (ccb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: - softc->atios_returned++; + softc->atios_freed++; break; case XPT_IMMEDIATE_NOTIFY: case XPT_NOTIFY_ACKNOWLEDGE: - softc->inots_returned++; + softc->inots_freed++; break; default: break; @@ -1002,20 +984,20 @@ ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb) ctl_free_io(ccb->ccb_h.io_ptr); free(ccb, M_CTLFE); - KASSERT(softc->atios_returned <= softc->atios_sent, ("%s: " - "atios_returned %ju > atios_sent %ju", __func__, - softc->atios_returned, softc->atios_sent)); - KASSERT(softc->inots_returned <= softc->inots_sent, ("%s: " - "inots_returned %ju > inots_sent %ju", __func__, - softc->inots_returned, softc->inots_sent)); + KASSERT(softc->atios_freed <= softc->atios_alloced, ("%s: " + "atios_freed %ju > atios_alloced %ju", __func__, + softc->atios_freed, softc->atios_alloced)); + KASSERT(softc->inots_freed <= softc->inots_alloced, ("%s: " + "inots_freed %ju > inots_alloced %ju", __func__, + softc->inots_freed, softc->inots_alloced)); /* * If we have received all of our CCBs, we can release our * reference on the peripheral driver. It will probably go away * now. */ - if ((softc->atios_returned == softc->atios_sent) - && (softc->inots_returned == softc->inots_sent)) { + if ((softc->atios_freed == softc->atios_alloced) + && (softc->inots_freed == softc->inots_alloced)) { cam_periph_release_locked(periph); } } @@ -1105,6 +1087,19 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) done_ccb->ccb_h.func_code); #endif + /* + * At this point CTL has no known use case for device queue freezes. + * In case some SIM think different -- drop its freeze right here. + */ + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(periph->path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; + } + softc = (struct ctlfe_lun_softc *)periph->softc; bus_softc = softc->parent_softc; mtx = cam_periph_mtx(periph); @@ -1135,8 +1130,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) atio = &done_ccb->atio; - softc->atios_returned++; - resubmit: /* * Allocate a ctl_io, pass it to CTL, and wait for the @@ -1291,7 +1284,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) if (periph->flags & CAM_PERIPH_INVALID) { ctlfe_free_ccb(periph, (union ccb *)atio); } else { - softc->atios_sent++; mtx_unlock(mtx); xpt_action((union ccb *)atio); return; @@ -1418,14 +1410,9 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) union ctl_io *io; struct ccb_immediate_notify *inot; cam_status status; - int frozen, send_ctl_io; + int send_ctl_io; inot = &done_ccb->cin1; - - softc->inots_returned++; - - frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0; - printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x " "seq %#x\n", __func__, inot->ccb_h.status, inot->tag_id, inot->seq_id); @@ -1527,14 +1514,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; xpt_action(done_ccb); } - - if (frozen != 0) { - cam_release_devq(periph->path, - /*relsim_flags*/ 0, - /*opening reduction*/ 0, - /*timeout*/ 0, - /*getcount_only*/ 0); - } break; } case XPT_NOTIFY_ACKNOWLEDGE: @@ -1543,7 +1522,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) */ done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; xpt_action(done_ccb); - softc->inots_sent++; break; case XPT_SET_SIM_KNOB: case XPT_GET_SIM_KNOB: @@ -1820,7 +1798,7 @@ ctlfe_offline(void *arg) * CTL. So we only need to create a path/periph for this particular bus. */ static int -ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) +ctlfe_lun_enable(void *arg, int lun_id) { struct ctlfe_softc *bus_softc; struct ctlfe_lun_softc *softc; @@ -1831,8 +1809,7 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) bus_softc = (struct ctlfe_softc *)arg; status = xpt_create_path(&path, /*periph*/ NULL, - bus_softc->path_id, - targ_id.id, lun_id); + bus_softc->path_id, 0, lun_id); /* XXX KDM need some way to return status to CTL here? */ if (status != CAM_REQ_CMP) { printf("%s: could not create path, status %#x\n", __func__, @@ -1883,7 +1860,7 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) * on every bus that is attached to CTL. */ static int -ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) +ctlfe_lun_disable(void *arg, int lun_id) { struct ctlfe_softc *softc; struct ctlfe_lun_softc *lun_softc; @@ -1896,15 +1873,14 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) path = lun_softc->periph->path; - if ((xpt_path_target_id(path) == targ_id.id) + if ((xpt_path_target_id(path) == 0) && (xpt_path_lun_id(path) == lun_id)) { break; } } if (lun_softc == NULL) { mtx_unlock(&softc->lun_softc_mtx); - printf("%s: can't find target %d lun %d\n", __func__, - targ_id.id, lun_id); + printf("%s: can't find lun %d\n", __func__, lun_id); return (1); } cam_periph_acquire(lun_softc->periph); @@ -2043,7 +2019,6 @@ ctlfe_done(union ctl_io *io) if (periph->flags & CAM_PERIPH_INVALID) { ctlfe_free_ccb(periph, ccb); } else { - softc->atios_sent++; cam_periph_unlock(periph); xpt_action(ccb); return; diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index a429259..8f27fd9 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -6453,6 +6453,830 @@ bailout: return (retval); } +struct scsi_attrib_table_entry scsi_mam_attr_table[] = { + { SMA_ATTR_REM_CAP_PARTITION, SCSI_ATTR_FLAG_NONE, + "Remaining Capacity in Partition", + /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf,/*parse_str*/ NULL }, + { SMA_ATTR_MAX_CAP_PARTITION, SCSI_ATTR_FLAG_NONE, + "Maximum Capacity in Partition", + /*suffix*/"MB", /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, + { SMA_ATTR_TAPEALERT_FLAGS, SCSI_ATTR_FLAG_HEX, + "TapeAlert Flags", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, + { SMA_ATTR_LOAD_COUNT, SCSI_ATTR_FLAG_NONE, + "Load Count", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, + { SMA_ATTR_MAM_SPACE_REMAINING, SCSI_ATTR_FLAG_NONE, + "MAM Space Remaining", + /*suffix*/"bytes", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_DEV_ASSIGNING_ORG, SCSI_ATTR_FLAG_NONE, + "Assigning Organization", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_FORMAT_DENSITY_CODE, SCSI_ATTR_FLAG_HEX, + "Format Density Code", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, + { SMA_ATTR_INITIALIZATION_COUNT, SCSI_ATTR_FLAG_NONE, + "Initialization Count", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, + { SMA_ATTR_VOLUME_ID, SCSI_ATTR_FLAG_NONE, + "Volume Identifier", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_VOLUME_CHANGE_REF, SCSI_ATTR_FLAG_HEX, + "Volume Change Reference", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_DEV_SERIAL_LAST_LOAD, SCSI_ATTR_FLAG_NONE, + "Device Vendor/Serial at Last Load", + /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_DEV_SERIAL_LAST_LOAD_1, SCSI_ATTR_FLAG_NONE, + "Device Vendor/Serial at Last Load - 1", + /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_DEV_SERIAL_LAST_LOAD_2, SCSI_ATTR_FLAG_NONE, + "Device Vendor/Serial at Last Load - 2", + /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_DEV_SERIAL_LAST_LOAD_3, SCSI_ATTR_FLAG_NONE, + "Device Vendor/Serial at Last Load - 3", + /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_TOTAL_MB_WRITTEN_LT, SCSI_ATTR_FLAG_NONE, + "Total MB Written in Medium Life", + /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_TOTAL_MB_READ_LT, SCSI_ATTR_FLAG_NONE, + "Total MB Read in Medium Life", + /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_TOTAL_MB_WRITTEN_CUR, SCSI_ATTR_FLAG_NONE, + "Total MB Written in Current/Last Load", + /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_TOTAL_MB_READ_CUR, SCSI_ATTR_FLAG_NONE, + "Total MB Read in Current/Last Load", + /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_FIRST_ENC_BLOCK, SCSI_ATTR_FLAG_NONE, + "Logical Position of First Encrypted Block", + /*suffix*/ NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_NEXT_UNENC_BLOCK, SCSI_ATTR_FLAG_NONE, + "Logical Position of First Unencrypted Block after First " + "Encrypted Block", + /*suffix*/ NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MEDIUM_USAGE_HIST, SCSI_ATTR_FLAG_NONE, + "Medium Usage History", + /*suffix*/ NULL, /*to_str*/ NULL, + /*parse_str*/ NULL }, + { SMA_ATTR_PART_USAGE_HIST, SCSI_ATTR_FLAG_NONE, + "Partition Usage History", + /*suffix*/ NULL, /*to_str*/ NULL, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_MANUF, SCSI_ATTR_FLAG_NONE, + "Medium Manufacturer", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_SERIAL, SCSI_ATTR_FLAG_NONE, + "Medium Serial Number", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_LENGTH, SCSI_ATTR_FLAG_NONE, + "Medium Length", + /*suffix*/"m", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_WIDTH, SCSI_ATTR_FLAG_FP | SCSI_ATTR_FLAG_DIV_10 | + SCSI_ATTR_FLAG_FP_1DIGIT, + "Medium Width", + /*suffix*/"mm", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_ASSIGNING_ORG, SCSI_ATTR_FLAG_NONE, + "Assigning Organization", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_DENSITY_CODE, SCSI_ATTR_FLAG_HEX, + "Medium Density Code", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_MANUF_DATE, SCSI_ATTR_FLAG_NONE, + "Medium Manufacture Date", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MAM_CAPACITY, SCSI_ATTR_FLAG_NONE, + "MAM Capacity", + /*suffix*/"bytes", /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_TYPE, SCSI_ATTR_FLAG_HEX, + "Medium Type", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_TYPE_INFO, SCSI_ATTR_FLAG_HEX, + "Medium Type Information", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MED_SERIAL_NUM, SCSI_ATTR_FLAG_NONE, + "Medium Serial Number", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_APP_VENDOR, SCSI_ATTR_FLAG_NONE, + "Application Vendor", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_APP_NAME, SCSI_ATTR_FLAG_NONE, + "Application Name", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_APP_VERSION, SCSI_ATTR_FLAG_NONE, + "Application Version", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_USER_MED_TEXT_LABEL, SCSI_ATTR_FLAG_NONE, + "User Medium Text Label", + /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_LAST_WRITTEN_TIME, SCSI_ATTR_FLAG_NONE, + "Date and Time Last Written", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_TEXT_LOCAL_ID, SCSI_ATTR_FLAG_HEX, + "Text Localization Identifier", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_BARCODE, SCSI_ATTR_FLAG_NONE, + "Barcode", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_HOST_OWNER_NAME, SCSI_ATTR_FLAG_NONE, + "Owning Host Textual Name", + /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_MEDIA_POOL, SCSI_ATTR_FLAG_NONE, + "Media Pool", + /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_PART_USER_LABEL, SCSI_ATTR_FLAG_NONE, + "Partition User Text Label", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_LOAD_UNLOAD_AT_PART, SCSI_ATTR_FLAG_NONE, + "Load/Unload at Partition", + /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_APP_FORMAT_VERSION, SCSI_ATTR_FLAG_NONE, + "Application Format Version", + /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, + /*parse_str*/ NULL }, + { SMA_ATTR_VOL_COHERENCY_INFO, SCSI_ATTR_FLAG_NONE, + "Volume Coherency Information", + /*suffix*/NULL, /*to_str*/ scsi_attrib_volcoh_sbuf, + /*parse_str*/ NULL }, + { 0x0ff1, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Creation", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x0ff2, SCSI_ATTR_FLAG_NONE, + "Spectra MLM C3", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x0ff3, SCSI_ATTR_FLAG_NONE, + "Spectra MLM RW", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x0ff4, SCSI_ATTR_FLAG_NONE, + "Spectra MLM SDC List", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x0ff7, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Post Scan", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x0ffe, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Checksum", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17f1, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Creation", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17f2, SCSI_ATTR_FLAG_NONE, + "Spectra MLM C3", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17f3, SCSI_ATTR_FLAG_NONE, + "Spectra MLM RW", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17f4, SCSI_ATTR_FLAG_NONE, + "Spectra MLM SDC List", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17f7, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Post Scan", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, + { 0x17ff, SCSI_ATTR_FLAG_NONE, + "Spectra MLM Checksum", + /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, + /*parse_str*/ NULL }, +}; + +/* + * Print out Volume Coherency Information (Attribute 0x080c). + * This field has two variable length members, including one at the + * beginning, so it isn't practical to have a fixed structure definition. + * This is current as of SSC4r03 (see section 4.2.21.3), dated March 25, + * 2013. + */ +int +scsi_attrib_volcoh_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + size_t avail_len; + uint32_t field_size; + uint64_t tmp_val; + uint8_t *cur_ptr; + int retval; + int vcr_len, as_len; + + retval = 0; + tmp_val = 0; + + field_size = scsi_2btoul(hdr->length); + avail_len = valid_len - sizeof(*hdr); + if (field_size > avail_len) { + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Available " + "length of attribute ID 0x%.4x %zu < field " + "length %u", scsi_2btoul(hdr->id), avail_len, + field_size); + } + retval = 1; + goto bailout; + } else if (field_size == 0) { + /* + * It isn't clear from the spec whether a field length of + * 0 is invalid here. It probably is, but be lenient here + * to avoid inconveniencing the user. + */ + goto bailout; + } + cur_ptr = hdr->attribute; + vcr_len = *cur_ptr; + cur_ptr++; + + sbuf_printf(sb, "\n\tVolume Change Reference Value:"); + + switch (vcr_len) { + case 0: + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Volume Change " + "Reference value has length of 0"); + } + retval = 1; + goto bailout; + break; /*NOTREACHED*/ + case 1: + tmp_val = *cur_ptr; + break; + case 2: + tmp_val = scsi_2btoul(cur_ptr); + break; + case 3: + tmp_val = scsi_3btoul(cur_ptr); + break; + case 4: + tmp_val = scsi_4btoul(cur_ptr); + break; + case 8: + tmp_val = scsi_8btou64(cur_ptr); + break; + default: + sbuf_printf(sb, "\n"); + sbuf_hexdump(sb, cur_ptr, vcr_len, NULL, 0); + break; + } + if (vcr_len <= 8) + sbuf_printf(sb, " 0x%jx\n", (uintmax_t)tmp_val); + + cur_ptr += vcr_len; + tmp_val = scsi_8btou64(cur_ptr); + sbuf_printf(sb, "\tVolume Coherency Count: %ju\n", (uintmax_t)tmp_val); + + cur_ptr += sizeof(tmp_val); + tmp_val = scsi_8btou64(cur_ptr); + sbuf_printf(sb, "\tVolume Coherency Set Identifier: 0x%jx\n", + (uintmax_t)tmp_val); + + /* + * Figure out how long the Application Client Specific Information + * is and produce a hexdump. + */ + cur_ptr += sizeof(tmp_val); + as_len = scsi_2btoul(cur_ptr); + cur_ptr += sizeof(uint16_t); + sbuf_printf(sb, "\tApplication Client Specific Information: "); + if (((as_len == SCSI_LTFS_VER0_LEN) + || (as_len == SCSI_LTFS_VER1_LEN)) + && (strncmp(cur_ptr, SCSI_LTFS_STR_NAME, SCSI_LTFS_STR_LEN) == 0)) { + sbuf_printf(sb, "LTFS\n"); + cur_ptr += SCSI_LTFS_STR_LEN + 1; + if (cur_ptr[SCSI_LTFS_UUID_LEN] != '\0') + cur_ptr[SCSI_LTFS_UUID_LEN] = '\0'; + sbuf_printf(sb, "\tLTFS UUID: %s\n", cur_ptr); + cur_ptr += SCSI_LTFS_UUID_LEN + 1; + /* XXX KDM check the length */ + sbuf_printf(sb, "\tLTFS Version: %d\n", *cur_ptr); + } else { + sbuf_printf(sb, "Unknown\n"); + sbuf_hexdump(sb, cur_ptr, as_len, NULL, 0); + } + +bailout: + return (retval); +} + +int +scsi_attrib_vendser_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + size_t avail_len; + uint32_t field_size; + struct scsi_attrib_vendser *vendser; + cam_strvis_flags strvis_flags; + int retval = 0; + + field_size = scsi_2btoul(hdr->length); + avail_len = valid_len - sizeof(*hdr); + if (field_size > avail_len) { + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Available " + "length of attribute ID 0x%.4x %zu < field " + "length %u", scsi_2btoul(hdr->id), avail_len, + field_size); + } + retval = 1; + goto bailout; + } else if (field_size == 0) { + /* + * A field size of 0 doesn't make sense here. The device + * can at least give you the vendor ID, even if it can't + * give you the serial number. + */ + if (error_str != NULL) { + snprintf(error_str, error_str_len, "The length of " + "attribute ID 0x%.4x is 0", + scsi_2btoul(hdr->id)); + } + retval = 1; + goto bailout; + } + vendser = (struct scsi_attrib_vendser *)hdr->attribute; + + switch (output_flags & SCSI_ATTR_OUTPUT_NONASCII_MASK) { + case SCSI_ATTR_OUTPUT_NONASCII_TRIM: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_TRIM; + break; + case SCSI_ATTR_OUTPUT_NONASCII_RAW: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_RAW; + break; + case SCSI_ATTR_OUTPUT_NONASCII_ESC: + default: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_ESC; + break;; + } + cam_strvis_sbuf(sb, vendser->vendor, sizeof(vendser->vendor), + strvis_flags); + sbuf_putc(sb, ' '); + cam_strvis_sbuf(sb, vendser->serial_num, sizeof(vendser->serial_num), + strvis_flags); +bailout: + return (retval); +} + +int +scsi_attrib_hexdump_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + uint32_t field_size; + ssize_t avail_len; + uint32_t print_len; + uint8_t *num_ptr; + int retval = 0; + + field_size = scsi_2btoul(hdr->length); + avail_len = valid_len - sizeof(*hdr); + print_len = MIN(avail_len, field_size); + num_ptr = hdr->attribute; + + if (print_len > 0) { + sbuf_printf(sb, "\n"); + sbuf_hexdump(sb, num_ptr, print_len, NULL, 0); + } + + return (retval); +} + +int +scsi_attrib_int_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + uint64_t print_number; + size_t avail_len; + uint32_t number_size; + int retval = 0; + + number_size = scsi_2btoul(hdr->length); + + avail_len = valid_len - sizeof(*hdr); + if (avail_len < number_size) { + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Available " + "length of attribute ID 0x%.4x %zu < field " + "length %u", scsi_2btoul(hdr->id), avail_len, + number_size); + } + retval = 1; + goto bailout; + } + + switch (number_size) { + case 0: + /* + * We don't treat this as an error, since there may be + * scenarios where a device reports a field but then gives + * a length of 0. See the note in scsi_attrib_ascii_sbuf(). + */ + goto bailout; + break; /*NOTREACHED*/ + case 1: + print_number = hdr->attribute[0]; + break; + case 2: + print_number = scsi_2btoul(hdr->attribute); + break; + case 3: + print_number = scsi_3btoul(hdr->attribute); + break; + case 4: + print_number = scsi_4btoul(hdr->attribute); + break; + case 8: + print_number = scsi_8btou64(hdr->attribute); + break; + default: + /* + * If we wind up here, the number is too big to print + * normally, so just do a hexdump. + */ + retval = scsi_attrib_hexdump_sbuf(sb, hdr, valid_len, + flags, output_flags, + error_str, error_str_len); + goto bailout; + break; + } + + if (flags & SCSI_ATTR_FLAG_FP) { +#ifndef _KERNEL + long double num_float; + + num_float = (long double)print_number; + + if (flags & SCSI_ATTR_FLAG_DIV_10) + num_float /= 10; + + sbuf_printf(sb, "%.*Lf", (flags & SCSI_ATTR_FLAG_FP_1DIGIT) ? + 1 : 0, num_float); +#else /* _KERNEL */ + sbuf_printf(sb, "%ju", (flags & SCSI_ATTR_FLAG_DIV_10) ? + (print_number / 10) : print_number); +#endif /* _KERNEL */ + } else if (flags & SCSI_ATTR_FLAG_HEX) { + sbuf_printf(sb, "0x%jx", (uintmax_t)print_number); + } else + sbuf_printf(sb, "%ju", (uintmax_t)print_number); + +bailout: + return (retval); +} + +int +scsi_attrib_ascii_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + size_t avail_len; + uint32_t field_size, print_size; + int retval = 0; + + avail_len = valid_len - sizeof(*hdr); + field_size = scsi_2btoul(hdr->length); + print_size = MIN(avail_len, field_size); + + if (print_size > 0) { + cam_strvis_flags strvis_flags; + + switch (output_flags & SCSI_ATTR_OUTPUT_NONASCII_MASK) { + case SCSI_ATTR_OUTPUT_NONASCII_TRIM: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_TRIM; + break; + case SCSI_ATTR_OUTPUT_NONASCII_RAW: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_RAW; + break; + case SCSI_ATTR_OUTPUT_NONASCII_ESC: + default: + strvis_flags = CAM_STRVIS_FLAG_NONASCII_ESC; + break; + } + cam_strvis_sbuf(sb, hdr->attribute, print_size, strvis_flags); + } else if (avail_len < field_size) { + /* + * We only report an error if the user didn't allocate + * enough space to hold the full value of this field. If + * the field length is 0, that is allowed by the spec. + * e.g. in SPC-4r37, section 7.4.2.2.5, VOLUME IDENTIFIER + * "This attribute indicates the current volume identifier + * (see SMC-3) of the medium. If the device server supports + * this attribute but does not have access to the volume + * identifier, the device server shall report this attribute + * with an attribute length value of zero." + */ + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Available " + "length of attribute ID 0x%.4x %zu < field " + "length %u", scsi_2btoul(hdr->id), avail_len, + field_size); + } + retval = 1; + } + + return (retval); +} + +int +scsi_attrib_text_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len) +{ + size_t avail_len; + uint32_t field_size, print_size; + int retval = 0; + int esc_text = 1; + + avail_len = valid_len - sizeof(*hdr); + field_size = scsi_2btoul(hdr->length); + print_size = MIN(avail_len, field_size); + + if ((output_flags & SCSI_ATTR_OUTPUT_TEXT_MASK) == + SCSI_ATTR_OUTPUT_TEXT_RAW) + esc_text = 0; + + if (print_size > 0) { + uint32_t i; + + for (i = 0; i < print_size; i++) { + if (hdr->attribute[i] == '\0') + continue; + else if (((unsigned char)hdr->attribute[i] < 0x80) + || (esc_text == 0)) + sbuf_putc(sb, hdr->attribute[i]); + else + sbuf_printf(sb, "%%%02x", + (unsigned char)hdr->attribute[i]); + } + } else if (avail_len < field_size) { + /* + * We only report an error if the user didn't allocate + * enough space to hold the full value of this field. + */ + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Available " + "length of attribute ID 0x%.4x %zu < field " + "length %u", scsi_2btoul(hdr->id), avail_len, + field_size); + } + retval = 1; + } + + return (retval); +} + +struct scsi_attrib_table_entry * +scsi_find_attrib_entry(struct scsi_attrib_table_entry *table, + size_t num_table_entries, uint32_t id) +{ + uint32_t i; + + for (i = 0; i < num_table_entries; i++) { + if (table[i].id == id) + return (&table[i]); + } + + return (NULL); +} + +struct scsi_attrib_table_entry * +scsi_get_attrib_entry(uint32_t id) +{ + return (scsi_find_attrib_entry(scsi_mam_attr_table, + sizeof(scsi_mam_attr_table) / sizeof(scsi_mam_attr_table[0]), + id)); +} + +int +scsi_attrib_value_sbuf(struct sbuf *sb, uint32_t valid_len, + struct scsi_mam_attribute_header *hdr, uint32_t output_flags, + char *error_str, size_t error_str_len) +{ + int retval; + + switch (hdr->byte2 & SMA_FORMAT_MASK) { + case SMA_FORMAT_ASCII: + retval = scsi_attrib_ascii_sbuf(sb, hdr, valid_len, + SCSI_ATTR_FLAG_NONE, output_flags, error_str,error_str_len); + break; + case SMA_FORMAT_BINARY: + if (scsi_2btoul(hdr->length) <= 8) + retval = scsi_attrib_int_sbuf(sb, hdr, valid_len, + SCSI_ATTR_FLAG_NONE, output_flags, error_str, + error_str_len); + else + retval = scsi_attrib_hexdump_sbuf(sb, hdr, valid_len, + SCSI_ATTR_FLAG_NONE, output_flags, error_str, + error_str_len); + break; + case SMA_FORMAT_TEXT: + retval = scsi_attrib_text_sbuf(sb, hdr, valid_len, + SCSI_ATTR_FLAG_NONE, output_flags, error_str, + error_str_len); + break; + default: + if (error_str != NULL) { + snprintf(error_str, error_str_len, "Unknown attribute " + "format 0x%x", hdr->byte2 & SMA_FORMAT_MASK); + } + retval = 1; + goto bailout; + break; /*NOTREACHED*/ + } + + sbuf_trim(sb); + +bailout: + + return (retval); +} + +void +scsi_attrib_prefix_sbuf(struct sbuf *sb, uint32_t output_flags, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, const char *desc) +{ + int need_space = 0; + uint32_t len; + uint32_t id; + + /* + * We can't do anything if we don't have enough valid data for the + * header. + */ + if (valid_len < sizeof(*hdr)) + return; + + id = scsi_2btoul(hdr->id); + /* + * Note that we print out the value of the attribute listed in the + * header, regardless of whether we actually got that many bytes + * back from the device through the controller. A truncated result + * could be the result of a failure to ask for enough data; the + * header indicates how many bytes are allocated for this attribute + * in the MAM. + */ + len = scsi_2btoul(hdr->length); + + if ((output_flags & SCSI_ATTR_OUTPUT_FIELD_MASK) == + SCSI_ATTR_OUTPUT_FIELD_NONE) + return; + + if ((output_flags & SCSI_ATTR_OUTPUT_FIELD_DESC) + && (desc != NULL)) { + sbuf_printf(sb, "%s", desc); + need_space = 1; + } + + if (output_flags & SCSI_ATTR_OUTPUT_FIELD_NUM) { + sbuf_printf(sb, "%s(0x%.4x)", (need_space) ? " " : "", id); + need_space = 0; + } + + if (output_flags & SCSI_ATTR_OUTPUT_FIELD_SIZE) { + sbuf_printf(sb, "%s[%d]", (need_space) ? " " : "", len); + need_space = 0; + } + if (output_flags & SCSI_ATTR_OUTPUT_FIELD_RW) { + sbuf_printf(sb, "%s(%s)", (need_space) ? " " : "", + (hdr->byte2 & SMA_READ_ONLY) ? "RO" : "RW"); + } + sbuf_printf(sb, ": "); +} + +int +scsi_attrib_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, struct scsi_attrib_table_entry *user_table, + size_t num_user_entries, int prefer_user_table, + uint32_t output_flags, char *error_str, int error_str_len) +{ + int retval; + struct scsi_attrib_table_entry *table1 = NULL, *table2 = NULL; + struct scsi_attrib_table_entry *entry = NULL; + size_t table1_size = 0, table2_size = 0; + uint32_t id; + + retval = 0; + + if (valid_len < sizeof(*hdr)) { + retval = 1; + goto bailout; + } + + id = scsi_2btoul(hdr->id); + + if (user_table != NULL) { + if (prefer_user_table != 0) { + table1 = user_table; + table1_size = num_user_entries; + table2 = scsi_mam_attr_table; + table2_size = sizeof(scsi_mam_attr_table) / + sizeof(scsi_mam_attr_table[0]); + } else { + table1 = scsi_mam_attr_table; + table1_size = sizeof(scsi_mam_attr_table) / + sizeof(scsi_mam_attr_table[0]); + table2 = user_table; + table2_size = num_user_entries; + } + } else { + table1 = scsi_mam_attr_table; + table1_size = sizeof(scsi_mam_attr_table) / + sizeof(scsi_mam_attr_table[0]); + } + + entry = scsi_find_attrib_entry(table1, table1_size, id); + if (entry != NULL) { + scsi_attrib_prefix_sbuf(sb, output_flags, hdr, valid_len, + entry->desc); + if (entry->to_str == NULL) + goto print_default; + retval = entry->to_str(sb, hdr, valid_len, entry->flags, + output_flags, error_str, error_str_len); + goto bailout; + } + if (table2 != NULL) { + entry = scsi_find_attrib_entry(table2, table2_size, id); + if (entry != NULL) { + if (entry->to_str == NULL) + goto print_default; + + scsi_attrib_prefix_sbuf(sb, output_flags, hdr, + valid_len, entry->desc); + retval = entry->to_str(sb, hdr, valid_len, entry->flags, + output_flags, error_str, + error_str_len); + goto bailout; + } + } + + scsi_attrib_prefix_sbuf(sb, output_flags, hdr, valid_len, NULL); + +print_default: + retval = scsi_attrib_value_sbuf(sb, valid_len, hdr, output_flags, + error_str, error_str_len); +bailout: + if (retval == 0) { + if ((entry != NULL) + && (entry->suffix != NULL)) + sbuf_printf(sb, " %s", entry->suffix); + + sbuf_trim(sb); + sbuf_printf(sb, "\n"); + } + + return (retval); +} + void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), @@ -7403,6 +8227,74 @@ scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, timeout); } +void +scsi_read_attribute(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t service_action, + uint32_t element, u_int8_t elem_type, int logical_volume, + int partition, u_int32_t first_attribute, int cache, + u_int8_t *data_ptr, u_int32_t length, int sense_len, + u_int32_t timeout) +{ + struct scsi_read_attribute *scsi_cmd; + + scsi_cmd = (struct scsi_read_attribute *)&csio->cdb_io.cdb_bytes; + bzero(scsi_cmd, sizeof(*scsi_cmd)); + + scsi_cmd->opcode = READ_ATTRIBUTE; + scsi_cmd->service_action = service_action, + scsi_ulto2b(element, scsi_cmd->element); + scsi_cmd->elem_type = elem_type; + scsi_cmd->logical_volume = logical_volume; + scsi_cmd->partition = partition; + scsi_ulto2b(first_attribute, scsi_cmd->first_attribute); + scsi_ulto4b(length, scsi_cmd->length); + if (cache != 0) + scsi_cmd->cache |= SRA_CACHE; + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_IN, + tag_action, + /*data_ptr*/data_ptr, + /*dxfer_len*/length, + sense_len, + sizeof(*scsi_cmd), + timeout); +} + +void +scsi_write_attribute(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, uint32_t element, int logical_volume, + int partition, int wtc, u_int8_t *data_ptr, + u_int32_t length, int sense_len, u_int32_t timeout) +{ + struct scsi_write_attribute *scsi_cmd; + + scsi_cmd = (struct scsi_write_attribute *)&csio->cdb_io.cdb_bytes; + bzero(scsi_cmd, sizeof(*scsi_cmd)); + + scsi_cmd->opcode = WRITE_ATTRIBUTE; + if (wtc != 0) + scsi_cmd->byte2 = SWA_WTC; + scsi_ulto3b(element, scsi_cmd->element); + scsi_cmd->logical_volume = logical_volume; + scsi_cmd->partition = partition; + scsi_ulto4b(length, scsi_cmd->length); + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_OUT, + tag_action, + /*data_ptr*/data_ptr, + /*dxfer_len*/length, + sense_len, + sizeof(*scsi_cmd), + timeout); +} void scsi_persistent_reserve_in(struct ccb_scsiio *csio, uint32_t retries, diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index f70b094..e446f6c 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -996,6 +996,216 @@ struct scsi_write_buffer u_int8_t control; }; +struct scsi_read_attribute +{ + u_int8_t opcode; + u_int8_t service_action; +#define SRA_SA_ATTR_VALUES 0x00 +#define SRA_SA_ATTR_LIST 0x01 +#define SRA_SA_LOG_VOL_LIST 0x02 +#define SRA_SA_PART_LIST 0x03 +#define SRA_SA_RESTRICTED 0x04 +#define SRA_SA_SUPPORTED_ATTRS 0x05 +#define SRA_SA_MASK 0x1f + u_int8_t element[2]; + u_int8_t elem_type; + u_int8_t logical_volume; + u_int8_t reserved1; + u_int8_t partition; + u_int8_t first_attribute[2]; + u_int8_t length[4]; + u_int8_t cache; +#define SRA_CACHE 0x01 + u_int8_t control; +}; + +struct scsi_write_attribute +{ + u_int8_t opcode; + u_int8_t byte2; +#define SWA_WTC 0x01 + u_int8_t element[3]; + u_int8_t logical_volume; + u_int8_t reserved1; + u_int8_t partition; + u_int8_t reserved2[2]; + u_int8_t length[4]; + u_int8_t reserved3; + u_int8_t control; +}; + + +struct scsi_read_attribute_values +{ + u_int8_t length[4]; + u_int8_t attribute_0[0]; +}; + +struct scsi_mam_attribute_header +{ + u_int8_t id[2]; + /* + * Attributes obtained from SPC-4r36g (section 7.4.2.2) and + * SSC-4r03 (section 4.2.21). + */ +#define SMA_ATTR_ID_DEVICE_MIN 0x0000 + +#define SMA_ATTR_REM_CAP_PARTITION 0x0000 +#define SMA_ATTR_MAX_CAP_PARTITION 0x0001 +#define SMA_ATTR_TAPEALERT_FLAGS 0x0002 +#define SMA_ATTR_LOAD_COUNT 0x0003 +#define SMA_ATTR_MAM_SPACE_REMAINING 0x0004 + +#define SMA_ATTR_DEV_ASSIGNING_ORG 0x0005 +#define SMA_ATTR_FORMAT_DENSITY_CODE 0x0006 +#define SMA_ATTR_INITIALIZATION_COUNT 0x0007 +#define SMA_ATTR_VOLUME_ID 0x0008 +#define SMA_ATTR_VOLUME_CHANGE_REF 0x0009 + +#define SMA_ATTR_DEV_SERIAL_LAST_LOAD 0x020a +#define SMA_ATTR_DEV_SERIAL_LAST_LOAD_1 0x020b +#define SMA_ATTR_DEV_SERIAL_LAST_LOAD_2 0x020c +#define SMA_ATTR_DEV_SERIAL_LAST_LOAD_3 0x020d + +#define SMA_ATTR_TOTAL_MB_WRITTEN_LT 0x0220 +#define SMA_ATTR_TOTAL_MB_READ_LT 0x0221 +#define SMA_ATTR_TOTAL_MB_WRITTEN_CUR 0x0222 +#define SMA_ATTR_TOTAL_MB_READ_CUR 0x0223 +#define SMA_ATTR_FIRST_ENC_BLOCK 0x0224 +#define SMA_ATTR_NEXT_UNENC_BLOCK 0x0225 + +#define SMA_ATTR_MEDIUM_USAGE_HIST 0x0340 +#define SMA_ATTR_PART_USAGE_HIST 0x0341 + +#define SMA_ATTR_ID_DEVICE_MAX 0x03ff + +#define SMA_ATTR_ID_MEDIUM_MIN 0x0400 + +#define SMA_ATTR_MED_MANUF 0x0400 +#define SMA_ATTR_MED_SERIAL 0x0401 + +#define SMA_ATTR_MED_LENGTH 0x0402 +#define SMA_ATTR_MED_WIDTH 0x0403 +#define SMA_ATTR_MED_ASSIGNING_ORG 0x0404 +#define SMA_ATTR_MED_DENSITY_CODE 0x0405 + +#define SMA_ATTR_MED_MANUF_DATE 0x0406 +#define SMA_ATTR_MAM_CAPACITY 0x0407 +#define SMA_ATTR_MED_TYPE 0x0408 +#define SMA_ATTR_MED_TYPE_INFO 0x0409 +#define SMA_ATTR_MED_SERIAL_NUM 0x040a + +#define SMA_ATTR_ID_MEDIUM_MAX 0x07ff + +#define SMA_ATTR_ID_HOST_MIN 0x0800 + +#define SMA_ATTR_APP_VENDOR 0x0800 +#define SMA_ATTR_APP_NAME 0x0801 +#define SMA_ATTR_APP_VERSION 0x0802 +#define SMA_ATTR_USER_MED_TEXT_LABEL 0x0803 +#define SMA_ATTR_LAST_WRITTEN_TIME 0x0804 +#define SMA_ATTR_TEXT_LOCAL_ID 0x0805 +#define SMA_ATTR_BARCODE 0x0806 +#define SMA_ATTR_HOST_OWNER_NAME 0x0807 +#define SMA_ATTR_MEDIA_POOL 0x0808 +#define SMA_ATTR_PART_USER_LABEL 0x0809 +#define SMA_ATTR_LOAD_UNLOAD_AT_PART 0x080a +#define SMA_ATTR_APP_FORMAT_VERSION 0x080b +#define SMA_ATTR_VOL_COHERENCY_INFO 0x080c + +#define SMA_ATTR_ID_HOST_MAX 0x0bff + +#define SMA_ATTR_VENDOR_DEVICE_MIN 0x0c00 +#define SMA_ATTR_VENDOR_DEVICE_MAX 0x0fff +#define SMA_ATTR_VENDOR_MEDIUM_MIN 0x1000 +#define SMA_ATTR_VENDOR_MEDIUM_MAX 0x13ff +#define SMA_ATTR_VENDOR_HOST_MIN 0x1400 +#define SMA_ATTR_VENDOR_HOST_MAX 0x17ff + u_int8_t byte2; +#define SMA_FORMAT_BINARY 0x00 +#define SMA_FORMAT_ASCII 0x01 +#define SMA_FORMAT_TEXT 0x02 +#define SMA_FORMAT_MASK 0x03 +#define SMA_READ_ONLY 0x80 + u_int8_t length[2]; + u_int8_t attribute[0]; +}; + +struct scsi_attrib_list_header { + u_int8_t length[4]; + u_int8_t first_attr_0[0]; +}; + +struct scsi_attrib_lv_list { + u_int8_t length[2]; + u_int8_t first_lv_number; + u_int8_t num_logical_volumes; +}; + +struct scsi_attrib_vendser { + uint8_t vendor[8]; + uint8_t serial_num[32]; +}; + +/* + * These values are used to decode the Volume Coherency Information + * Attribute (0x080c) for LTFS-format coherency information. + * Although the Application Client Specific lengths are different for + * Version 0 and Version 1, the data is in fact the same. The length + * difference was due to a code bug. + */ +#define SCSI_LTFS_VER0_LEN 42 +#define SCSI_LTFS_VER1_LEN 43 +#define SCSI_LTFS_UUID_LEN 36 +#define SCSI_LTFS_STR_NAME "LTFS" +#define SCSI_LTFS_STR_LEN 4 + +typedef enum { + SCSI_ATTR_FLAG_NONE = 0x00, + SCSI_ATTR_FLAG_HEX = 0x01, + SCSI_ATTR_FLAG_FP = 0x02, + SCSI_ATTR_FLAG_DIV_10 = 0x04, + SCSI_ATTR_FLAG_FP_1DIGIT = 0x08 +} scsi_attrib_flags; + +typedef enum { + SCSI_ATTR_OUTPUT_NONE = 0x00, + SCSI_ATTR_OUTPUT_TEXT_MASK = 0x03, + SCSI_ATTR_OUTPUT_TEXT_RAW = 0x00, + SCSI_ATTR_OUTPUT_TEXT_ESC = 0x01, + SCSI_ATTR_OUTPUT_TEXT_RSV1 = 0x02, + SCSI_ATTR_OUTPUT_TEXT_RSV2 = 0x03, + SCSI_ATTR_OUTPUT_NONASCII_MASK = 0x0c, + SCSI_ATTR_OUTPUT_NONASCII_TRIM = 0x00, + SCSI_ATTR_OUTPUT_NONASCII_ESC = 0x04, + SCSI_ATTR_OUTPUT_NONASCII_RAW = 0x08, + SCSI_ATTR_OUTPUT_NONASCII_RSV1 = 0x0c, + SCSI_ATTR_OUTPUT_FIELD_MASK = 0xf0, + SCSI_ATTR_OUTPUT_FIELD_ALL = 0xf0, + SCSI_ATTR_OUTPUT_FIELD_NONE = 0x00, + SCSI_ATTR_OUTPUT_FIELD_DESC = 0x10, + SCSI_ATTR_OUTPUT_FIELD_NUM = 0x20, + SCSI_ATTR_OUTPUT_FIELD_SIZE = 0x40, + SCSI_ATTR_OUTPUT_FIELD_RW = 0x80 +} scsi_attrib_output_flags; + +struct sbuf; + +struct scsi_attrib_table_entry +{ + u_int32_t id; + u_int32_t flags; + const char *desc; + const char *suffix; + int (*to_str)(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + int (*parse_str)(char *str, struct scsi_mam_attribute_header *hdr, + uint32_t alloc_len, uint32_t flags, char *error_str, + int error_str_len); +}; + struct scsi_rw_6 { u_int8_t opcode; @@ -1750,6 +1960,8 @@ struct ata_pass_16 { #define READ_16 0x88 #define COMPARE_AND_WRITE 0x89 #define WRITE_16 0x8A +#define READ_ATTRIBUTE 0x8C +#define WRITE_ATTRIBUTE 0x8D #define WRITE_VERIFY_16 0x8E #define VERIFY_16 0x8F #define SYNCHRONIZE_CACHE_16 0x91 @@ -3272,8 +3484,6 @@ struct cam_device; extern const char *scsi_sense_key_text[]; -struct sbuf; - __BEGIN_DECLS void scsi_sense_desc(int sense_key, int asc, int ascq, struct scsi_inquiry_data *inq_data, @@ -3465,6 +3675,63 @@ int scsi_parse_transportid(char *transportid_str, #endif char *error_str, int error_str_len); + +int scsi_attrib_volcoh_sbuf(struct sbuf *sb, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +int scsi_attrib_vendser_sbuf(struct sbuf *sb, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +int scsi_attrib_hexdump_sbuf(struct sbuf *sb, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +int scsi_attrib_int_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +int scsi_attrib_ascii_sbuf(struct sbuf *sb, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +int scsi_attrib_text_sbuf(struct sbuf *sb, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, uint32_t flags, + uint32_t output_flags, char *error_str, + int error_str_len); + +struct scsi_attrib_table_entry *scsi_find_attrib_entry( + struct scsi_attrib_table_entry *table, + size_t num_table_entries, uint32_t id); + +struct scsi_attrib_table_entry *scsi_get_attrib_entry(uint32_t id); + +int scsi_attrib_value_sbuf(struct sbuf *sb, uint32_t valid_len, + struct scsi_mam_attribute_header *hdr, + uint32_t output_flags, char *error_str, + size_t error_str_len); + +void scsi_attrib_prefix_sbuf(struct sbuf *sb, uint32_t output_flags, + struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, const char *desc); + +int scsi_attrib_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, + uint32_t valid_len, + struct scsi_attrib_table_entry *user_table, + size_t num_user_entries, int prefer_user_table, + uint32_t output_flags, char *error_str, int error_str_len); + void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), @@ -3659,6 +3926,18 @@ void scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int start, int load_eject, int immediate, u_int8_t sense_len, u_int32_t timeout); +void scsi_read_attribute(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t service_action, + uint32_t element, u_int8_t elem_type, + int logical_volume, int partition, + u_int32_t first_attribute, int cache, u_int8_t *data_ptr, + u_int32_t length, int sense_len, u_int32_t timeout); +void scsi_write_attribute(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, uint32_t element, + int logical_volume, int partition, int wtc, u_int8_t *data_ptr, + u_int32_t length, int sense_len, u_int32_t timeout); void scsi_security_protocol_in(struct ccb_scsiio *csio, uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 30ca7b9..affda74 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -1826,7 +1826,7 @@ arc_hdr_destroy(arc_buf_hdr_t *hdr) if (l2hdr != NULL) { trim_map_free(l2hdr->b_dev->l2ad_vdev, l2hdr->b_daddr, - hdr->b_size, 0); + l2hdr->b_asize, 0); list_remove(l2hdr->b_dev->l2ad_buflist, hdr); arc_buf_l2_cdata_free(hdr); ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); @@ -3868,7 +3868,7 @@ arc_release(arc_buf_t *buf, void *tag) vdev_space_update(l2hdr->b_dev->l2ad_vdev, -l2hdr->b_asize, 0, 0); trim_map_free(l2hdr->b_dev->l2ad_vdev, l2hdr->b_daddr, - hdr->b_size, 0); + l2hdr->b_asize, 0); kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t)); ARCSTAT_INCR(arcstat_l2_size, -buf_size); mutex_exit(&l2arc_buflist_mtx); @@ -4813,7 +4813,7 @@ l2arc_write_done(zio_t *zio) bytes_dropped += abl2->b_asize; hdr->b_l2hdr = NULL; trim_map_free(abl2->b_dev->l2ad_vdev, abl2->b_daddr, - hdr->b_size, 0); + abl2->b_asize, 0); kmem_free(abl2, sizeof (l2arc_buf_hdr_t)); ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c index ea3c688..2b55290 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -1298,6 +1298,16 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx) dbuf_dirty_record_t *dr, **drp; ASSERT(txg != 0); + + /* + * Due to our use of dn_nlevels below, this can only be called + * in open context, unless we are operating on the MOS. + * From syncing context, dn_nlevels may be different from the + * dn_nlevels used when dbuf was dirtied. + */ + ASSERT(db->db_objset == + dmu_objset_pool(db->db_objset)->dp_meta_objset || + txg != spa_syncing_txg(dmu_objset_spa(db->db_objset))); ASSERT(db->db_blkid != DMU_BONUS_BLKID); ASSERT0(db->db_level); ASSERT(MUTEX_HELD(&db->db_mtx)); @@ -1320,11 +1330,8 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx) ASSERT(db->db.db_size != 0); - /* - * Any space we accounted for in dp_dirty_* will be cleaned up by - * dsl_pool_sync(). This is relatively rare so the discrepancy - * is not a big deal. - */ + dsl_pool_undirty_space(dmu_objset_pool(dn->dn_objset), + dr->dr_accounted, txg); *drp = dr->dr_next; @@ -1339,7 +1346,7 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx) list_remove(&dr->dr_parent->dt.di.dr_children, dr); mutex_exit(&dr->dr_parent->dt.di.dr_mtx); } else if (db->db_blkid == DMU_SPILL_BLKID || - db->db_level+1 == dn->dn_nlevels) { + db->db_level + 1 == dn->dn_nlevels) { ASSERT(db->db_blkptr == NULL || db->db_parent == dn->dn_dbuf); mutex_enter(&dn->dn_mtx); list_remove(&dn->dn_dirty_records[txg & TXG_MASK], dr); @@ -1356,11 +1363,6 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx) VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data, db)); } - if (db->db_level != 0) { - mutex_destroy(&dr->dt.di.dr_mtx); - list_destroy(&dr->dt.di.dr_children); - } - kmem_free(dr, sizeof (dbuf_dirty_record_t)); ASSERT(db->db_dirtycnt > 0); @@ -2318,7 +2320,7 @@ dbuf_sync_indirect(dbuf_dirty_record_t *dr, dmu_tx_t *tx) zio = dr->dr_zio; mutex_enter(&dr->dt.di.dr_mtx); - dbuf_sync_list(&dr->dt.di.dr_children, tx); + dbuf_sync_list(&dr->dt.di.dr_children, db->db_level - 1, tx); ASSERT(list_head(&dr->dt.di.dr_children) == NULL); mutex_exit(&dr->dt.di.dr_mtx); zio_nowait(zio); @@ -2464,7 +2466,7 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx) } void -dbuf_sync_list(list_t *list, dmu_tx_t *tx) +dbuf_sync_list(list_t *list, int level, dmu_tx_t *tx) { dbuf_dirty_record_t *dr; @@ -2481,6 +2483,10 @@ dbuf_sync_list(list_t *list, dmu_tx_t *tx) DMU_META_DNODE_OBJECT); break; } + if (dr->dr_dbuf->db_blkid != DMU_BONUS_BLKID && + dr->dr_dbuf->db_blkid != DMU_SPILL_BLKID) { + VERIFY3U(dr->dr_dbuf->db_level, ==, level); + } list_remove(list, dr); if (dr->dr_dbuf->db_level > 0) dbuf_sync_indirect(dr, tx); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c index adee4f8..fd6e800 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c @@ -855,6 +855,10 @@ dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep) if (!dsl_dataset_is_snapshot(ds)) return (SET_ERROR(EINVAL)); + /* fromsnap, if provided, must be a snapshot */ + if (fromds != NULL && !dsl_dataset_is_snapshot(fromds)) + return (SET_ERROR(EINVAL)); + /* * fromsnap must be an earlier snapshot from the same fs as tosnap, * or the origin's fs. diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c index 1f42704..dff9fab 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #include <sys/dmu.h> @@ -686,7 +686,7 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len) uint64_t ibyte = i << shift; err = dnode_next_offset(dn, 0, &ibyte, 2, 1, 0); i = ibyte >> shift; - if (err == ESRCH) + if (err == ESRCH || i > end) break; if (err) { tx->tx_err = err; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c index 938b5d6..a6e0197 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -1492,6 +1492,16 @@ out: rw_downgrade(&dn->dn_struct_rwlock); } +static void +dnode_dirty_l1(dnode_t *dn, uint64_t l1blkid, dmu_tx_t *tx) +{ + dmu_buf_impl_t *db = dbuf_hold_level(dn, 1, l1blkid, FTAG); + if (db != NULL) { + dmu_buf_will_dirty(&db->db, tx); + dbuf_rele(db, FTAG); + } +} + void dnode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx) { @@ -1612,27 +1622,67 @@ dnode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx) nblks += 1; /* - * Dirty the first and last indirect blocks, as they (and/or their - * parents) will need to be written out if they were only - * partially freed. Interior indirect blocks will be themselves freed, - * by free_children(), so they need not be dirtied. Note that these - * interior blocks have already been prefetched by dmu_tx_hold_free(). + * Dirty all the indirect blocks in this range. Note that only + * the first and last indirect blocks can actually be written + * (if they were partially freed) -- they must be dirtied, even if + * they do not exist on disk yet. The interior blocks will + * be freed by free_children(), so they will not actually be written. + * Even though these interior blocks will not be written, we + * dirty them for two reasons: + * + * - It ensures that the indirect blocks remain in memory until + * syncing context. (They have already been prefetched by + * dmu_tx_hold_free(), so we don't have to worry about reading + * them serially here.) + * + * - The dirty space accounting will put pressure on the txg sync + * mechanism to begin syncing, and to delay transactions if there + * is a large amount of freeing. Even though these indirect + * blocks will not be written, we could need to write the same + * amount of space if we copy the freed BPs into deadlists. */ if (dn->dn_nlevels > 1) { uint64_t first, last; first = blkid >> epbs; - if (db = dbuf_hold_level(dn, 1, first, FTAG)) { - dmu_buf_will_dirty(&db->db, tx); - dbuf_rele(db, FTAG); - } + dnode_dirty_l1(dn, first, tx); if (trunc) last = dn->dn_maxblkid >> epbs; else last = (blkid + nblks - 1) >> epbs; - if (last > first && (db = dbuf_hold_level(dn, 1, last, FTAG))) { - dmu_buf_will_dirty(&db->db, tx); - dbuf_rele(db, FTAG); + if (last != first) + dnode_dirty_l1(dn, last, tx); + + int shift = dn->dn_datablkshift + dn->dn_indblkshift - + SPA_BLKPTRSHIFT; + for (uint64_t i = first + 1; i < last; i++) { + /* + * Set i to the blockid of the next non-hole + * level-1 indirect block at or after i. Note + * that dnode_next_offset() operates in terms of + * level-0-equivalent bytes. + */ + uint64_t ibyte = i << shift; + int err = dnode_next_offset(dn, DNODE_FIND_HAVELOCK, + &ibyte, 2, 1, 0); + i = ibyte >> shift; + if (i >= last) + break; + + /* + * Normally we should not see an error, either + * from dnode_next_offset() or dbuf_hold_level() + * (except for ESRCH from dnode_next_offset). + * If there is an i/o error, then when we read + * this block in syncing context, it will use + * ZIO_FLAG_MUSTSUCCEED, and thus hang/panic according + * to the "failmode" property. dnode_next_offset() + * doesn't have a flag to indicate MUSTSUCCEED. + */ + if (err != 0) + break; + + dnode_dirty_l1(dn, i, tx); } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c index 63bfc94..418d318 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -712,7 +712,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx) mutex_exit(&dn->dn_mtx); } - dbuf_sync_list(list, tx); + dbuf_sync_list(list, dn->dn_phys->dn_nlevels - 1, tx); if (!DMU_OBJECT_IS_SPECIAL(dn->dn_object)) { ASSERT3P(list_head(list), ==, NULL); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index 8700f4c..7c89454 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -2256,6 +2256,8 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config, return (error); ASSERT(spa->spa_root_vdev == rvd); + ASSERT3U(spa->spa_min_ashift, >=, SPA_MINBLOCKSHIFT); + ASSERT3U(spa->spa_max_ashift, <=, SPA_MAXBLOCKSHIFT); if (type != SPA_IMPORT_ASSEMBLE) { ASSERT(spa_guid(spa) == pool_guid); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c index d072dc3..994fb1c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. */ @@ -719,6 +719,9 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) spa->spa_debug = ((zfs_flags & ZFS_DEBUG_SPA) != 0); + spa->spa_min_ashift = INT_MAX; + spa->spa_max_ashift = 0; + /* * As a pool is being created, treat all features as disabled by * setting SPA_FEATURE_DISABLED for all entries in the feature diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h index 8be8ed6b..319406a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ @@ -287,7 +287,7 @@ void dbuf_evict(dmu_buf_impl_t *db); void dbuf_setdirty(dmu_buf_impl_t *db, dmu_tx_t *tx); void dbuf_unoverride(dbuf_dirty_record_t *dr); -void dbuf_sync_list(list_t *list, dmu_tx_t *tx); +void dbuf_sync_list(list_t *list, int level, dmu_tx_t *tx); void dbuf_release_bp(dmu_buf_impl_t *db); void dbuf_free_range(struct dnode *dn, uint64_t start, uint64_t end, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h index d1737e1..c656013 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. */ @@ -147,6 +147,8 @@ struct spa { objset_t *spa_meta_objset; /* copy of dp->dp_meta_objset */ txg_list_t spa_vdev_txg_list; /* per-txg dirty vdev list */ vdev_t *spa_root_vdev; /* top-level vdev container */ + int spa_min_ashift; /* of vdevs in normal class */ + int spa_max_ashift; /* of vdevs in normal class */ uint64_t spa_config_guid; /* config pool guid */ uint64_t spa_load_guid; /* spa_load initialized guid */ uint64_t spa_last_synced_guid; /* last synced guid */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h index e7515d5..c14ac21 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. */ #ifndef _SYS_VDEV_IMPL_H @@ -225,7 +225,7 @@ struct vdev { boolean_t vdev_isl2cache; /* was a l2cache device */ vdev_queue_t vdev_queue; /* I/O deadline schedule queue */ vdev_cache_t vdev_cache; /* physical block cache */ - spa_aux_vdev_t *vdev_aux; /* for l2cache vdevs */ + spa_aux_vdev_t *vdev_aux; /* for l2cache and spares vdevs */ zio_t *vdev_probe_zio; /* root of current probe */ vdev_aux_t vdev_label_aux; /* on-disk aux state */ struct trim_map *vdev_trimmap; /* map on outstanding trims */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c index a3ec38e..c434f0c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. */ @@ -278,8 +278,9 @@ vdev_add_child(vdev_t *pvd, vdev_t *cvd) size_t oldsize, newsize; uint64_t id = cvd->vdev_id; vdev_t **newchild; + spa_t *spa = cvd->vdev_spa; - ASSERT(spa_config_held(cvd->vdev_spa, SCL_ALL, RW_WRITER) == SCL_ALL); + ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); ASSERT(cvd->vdev_parent == NULL); cvd->vdev_parent = pvd; @@ -1398,6 +1399,17 @@ vdev_open(vdev_t *vd) } /* + * Track the min and max ashift values for normal data devices. + */ + if (vd->vdev_top == vd && vd->vdev_ashift != 0 && + !vd->vdev_islog && vd->vdev_aux == NULL) { + if (vd->vdev_ashift > spa->spa_max_ashift) + spa->spa_max_ashift = vd->vdev_ashift; + if (vd->vdev_ashift < spa->spa_min_ashift) + spa->spa_min_ashift = vd->vdev_ashift; + } + + /* * If a leaf vdev has a DTL, and seems healthy, then kick off a * resilver. But don't do this if we are doing a reopen for a scrub, * since this would just restart the scrub we are already doing. 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 5800db0..e3b6581 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 @@ -25,12 +25,11 @@ * All rights reserved. * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. * Copyright 2014 Xin Li <delphij@FreeBSD.org>. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. * Copyright (c) 2011, 2014 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved. */ /* @@ -5240,6 +5239,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc) static int zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist) { + nvpair_t *pair; nvlist_t *holds; int cleanup_fd = -1; int error; @@ -5249,6 +5249,19 @@ zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist) if (error != 0) return (SET_ERROR(EINVAL)); + /* make sure the user didn't pass us any invalid (empty) tags */ + for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL; + pair = nvlist_next_nvpair(holds, pair)) { + char *htag; + + error = nvpair_value_string(pair, &htag); + if (error != 0) + return (SET_ERROR(error)); + + if (strlen(htag) == 0) + return (SET_ERROR(EINVAL)); + } + if (nvlist_lookup_int32(args, "cleanup_fd", &cleanup_fd) == 0) { error = zfs_onexit_fd_hold(cleanup_fd, &minor); if (error != 0) @@ -5362,11 +5375,19 @@ zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl) return (error); error = dsl_dataset_hold(dp, lastsnap, FTAG, &new); + if (error == 0 && !dsl_dataset_is_snapshot(new)) { + dsl_dataset_rele(new, FTAG); + error = SET_ERROR(EINVAL); + } if (error != 0) { dsl_pool_rele(dp, FTAG); return (error); } error = dsl_dataset_hold(dp, firstsnap, FTAG, &old); + if (error == 0 && !dsl_dataset_is_snapshot(old)) { + dsl_dataset_rele(old, FTAG); + error = SET_ERROR(EINVAL); + } if (error != 0) { dsl_dataset_rele(new, FTAG); dsl_pool_rele(dp, FTAG); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 5bd6725..1038a87 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -5734,8 +5734,6 @@ zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int reqpage) object = mreq->object; error = 0; - KASSERT(vp->v_object == object, ("mismatching object")); - if (pcount > 1 && zp->z_blksz > PAGESIZE) { startoff = rounddown(IDX_TO_OFF(mreq->pindex), zp->z_blksz); reqstart = OFF_TO_IDX(round_page(startoff)); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c index e3b314f..3d30082 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c @@ -1797,7 +1797,6 @@ log: void zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) { - zfsvfs_t zfsvfs; uint64_t moid, obj, sa_obj, version; uint64_t sense = ZFS_CASE_SENSITIVE; uint64_t norm = 0; @@ -1805,6 +1804,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) int error; int i; znode_t *rootzp = NULL; + zfsvfs_t *zfsvfs; vattr_t vattr; znode_t *zp; zfs_acl_ids_t acl_ids; @@ -1880,7 +1880,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) vattr.va_uid = crgetuid(cr); vattr.va_gid = crgetgid(cr); - bzero(&zfsvfs, sizeof (zfsvfs_t)); + zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP); ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); @@ -1889,15 +1889,15 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) rootzp->z_atime_dirty = 0; rootzp->z_is_sa = USE_SA(version, os); - zfsvfs.z_os = os; - zfsvfs.z_parent = &zfsvfs; - zfsvfs.z_version = version; - zfsvfs.z_use_fuids = USE_FUIDS(version, os); - zfsvfs.z_use_sa = USE_SA(version, os); - zfsvfs.z_norm = norm; + zfsvfs->z_os = os; + zfsvfs->z_parent = zfsvfs; + zfsvfs->z_version = version; + zfsvfs->z_use_fuids = USE_FUIDS(version, os); + zfsvfs->z_use_sa = USE_SA(version, os); + zfsvfs->z_norm = norm; error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, - &zfsvfs.z_attr_table); + &zfsvfs->z_attr_table); ASSERT(error == 0); @@ -1906,16 +1906,16 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) * insensitive. */ if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED) - zfsvfs.z_norm |= U8_TEXTPREP_TOUPPER; + zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; - mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); - list_create(&zfsvfs.z_all_znodes, sizeof (znode_t), + mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); + list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), offsetof(znode_t, z_link_node)); for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) - mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); + mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); - rootzp->z_zfsvfs = &zfsvfs; + rootzp->z_zfsvfs = zfsvfs; VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, cr, NULL, &acl_ids)); zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); @@ -1932,12 +1932,13 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) * Create shares directory */ - error = zfs_create_share_dir(&zfsvfs, tx); + error = zfs_create_share_dir(zfsvfs, tx); ASSERT(error == 0); for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) - mutex_destroy(&zfsvfs.z_hold_mtx[i]); + mutex_destroy(&zfsvfs->z_hold_mtx[i]); + kmem_free(zfsvfs, sizeof (zfsvfs_t)); } #endif /* _KERNEL */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c index afda3e4..ae4d00c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. */ @@ -1264,19 +1264,23 @@ zio_write_bp_init(zio_t *zio) return (ZIO_PIPELINE_CONTINUE); } else { /* - * Round up compressed size to MINBLOCKSIZE and - * zero the tail. + * Round up compressed size up to the ashift + * of the smallest-ashift device, and zero the tail. + * This ensures that the compressed size of the BP + * (and thus compressratio property) are correct, + * in that we charge for the padding used to fill out + * the last sector. */ - size_t rounded = - P2ROUNDUP(psize, (size_t)SPA_MINBLOCKSIZE); - if (rounded > psize) { - bzero((char *)cbuf + psize, rounded - psize); - psize = rounded; - } - if (psize == lsize) { + ASSERT3U(spa->spa_min_ashift, >=, SPA_MINBLOCKSHIFT); + size_t rounded = (size_t)P2ROUNDUP(psize, + 1ULL << spa->spa_min_ashift); + if (rounded >= lsize) { compress = ZIO_COMPRESS_OFF; zio_buf_free(cbuf, lsize); + psize = lsize; } else { + bzero((char *)cbuf + psize, rounded - psize); + psize = rounded; zio_push_transform(zio, cbuf, psize, lsize, NULL); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h b/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h index 3003514..aa84f36 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h @@ -32,6 +32,9 @@ #include <sys/param.h> #include <sys/isa_defs.h> +#if defined(__FreeBSD__) && defined(_KERNEL) +#include <sys/libkern.h> +#endif #ifdef __cplusplus extern "C" { @@ -382,6 +385,9 @@ extern unsigned char bcd_to_byte[256]; static __inline int highbit(ulong_t i) { +#if defined(__FreeBSD__) && defined(_KERNEL) && defined(HAVE_INLINE_FLSL) + return (flsl(i)); +#else register int h = 1; if (i == 0) @@ -407,6 +413,7 @@ highbit(ulong_t i) h += 1; } return (h); +#endif } /* @@ -416,6 +423,9 @@ highbit(ulong_t i) static __inline int highbit64(uint64_t i) { +#if defined(__FreeBSD__) && defined(_KERNEL) && defined(HAVE_INLINE_FLSLL) + return (flsll(i)); +#else int h = 1; if (i == 0) @@ -439,6 +449,7 @@ highbit64(uint64_t i) h += 1; } return (h); +#endif } #ifdef __cplusplus diff --git a/sys/cddl/dev/dtrace/arm/dtrace_asm.S b/sys/cddl/dev/dtrace/arm/dtrace_asm.S index 06e91d2..fd0ce6c 100644 --- a/sys/cddl/dev/dtrace/arm/dtrace_asm.S +++ b/sys/cddl/dev/dtrace/arm/dtrace_asm.S @@ -28,7 +28,6 @@ #define _ASM #define _LOCORE -#define LOCORE #include <sys/cpuvar_defs.h> #include <sys/dtrace.h> diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c index 4031588..fcb5753 100644 --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -260,6 +260,8 @@ epoll_to_kevent(struct thread *td, struct file *epfp, *kev_flags |= EV_CLEAR; if ((levents & LINUX_EPOLLERR) != 0) *kev_flags |= EV_ERROR; + if ((levents & LINUX_EPOLLRDHUP) != 0) + *kev_flags |= EV_EOF; /* flags related to what event is registered */ if ((levents & LINUX_EPOLL_EVRD) != 0) { @@ -309,6 +311,8 @@ kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event) switch (kevent->filter) { case EVFILT_READ: l_event->events = LINUX_EPOLLIN|LINUX_EPOLLRDNORM|LINUX_EPOLLPRI; + if ((kevent->flags & EV_EOF) != 0) + l_event->events |= LINUX_EPOLLRDHUP; break; case EVFILT_WRITE: l_event->events = LINUX_EPOLLOUT|LINUX_EPOLLWRNORM; diff --git a/sys/compat/linux/linux_event.h b/sys/compat/linux/linux_event.h index 0c030ad..9b7d37b 100644 --- a/sys/compat/linux/linux_event.h +++ b/sys/compat/linux/linux_event.h @@ -49,7 +49,7 @@ |LINUX_EPOLLHUP|LINUX_EPOLLERR|LINUX_EPOLLPRI) #define LINUX_EPOLL_EVWR (LINUX_EPOLLOUT|LINUX_EPOLLWRNORM) #define LINUX_EPOLL_EVSUP (LINUX_EPOLLET|LINUX_EPOLLONESHOT \ - |LINUX_EPOLL_EVRD|LINUX_EPOLL_EVWR) + |LINUX_EPOLL_EVRD|LINUX_EPOLL_EVWR|LINUX_EPOLLRDHUP) #define LINUX_EPOLL_CTL_ADD 1 #define LINUX_EPOLL_CTL_DEL 2 diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 9251a20..1e5e37a 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -348,8 +348,7 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args, } else justone = 0; - error = getvnode(td->td_proc->p_fd, args->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, args->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c index 0fd47fd..394c26f 100644 --- a/sys/compat/linux/linux_fork.c +++ b/sys/compat/linux/linux_fork.c @@ -298,7 +298,7 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args) __rangeof(struct thread, td_startcopy, td_endcopy)); newtd->td_proc = p; - newtd->td_ucred = crhold(td->td_ucred); + thread_cow_get(newtd, td); /* create the emuldata */ linux_proc_init(td, newtd, args->flags); diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 65d27ba..fa5feaf 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -383,7 +383,7 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) */ PROC_LOCK(td->td_proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(td->td_proc, RLIMIT_DATA) || racct_set(td->td_proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(td->td_proc); @@ -1420,7 +1420,6 @@ int linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) { struct l_rlimit rlim; - struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; @@ -1437,9 +1436,7 @@ linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) if (which == -1) return (EINVAL); - PROC_LOCK(p); - lim_rlimit(p, which, &bsd_rlim); - PROC_UNLOCK(p); + lim_rlimit(td, which, &bsd_rlim); #ifdef COMPAT_LINUX32 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; @@ -1464,7 +1461,6 @@ int linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) { struct l_rlimit rlim; - struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; @@ -1481,9 +1477,7 @@ linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) if (which == -1) return (EINVAL); - PROC_LOCK(p); - lim_rlimit(p, which, &bsd_rlim); - PROC_UNLOCK(p); + lim_rlimit(td, which, &bsd_rlim); rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; @@ -2204,7 +2198,7 @@ linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args) if (args->old != NULL) { PROC_LOCK(p); - lim_rlimit(p, which, &rlim); + lim_rlimit_proc(p, which, &rlim); PROC_UNLOCK(p); if (rlim.rlim_cur == RLIM_INFINITY) lrlim.rlim_cur = LINUX_RLIM_INFINITY; diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c index f3bb09e..e61b49b 100644 --- a/sys/compat/svr4/imgact_svr4.c +++ b/sys/compat/svr4/imgact_svr4.c @@ -109,7 +109,7 @@ exec_svr4_imgact(imgp) */ PROC_LOCK(imgp->proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index c0da170..ec4504e 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -262,8 +262,7 @@ svr4_sys_getdents64(td, uap) DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n", uap->fd, uap->nbytes)); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); @@ -442,8 +441,7 @@ svr4_sys_getdents(td, uap) if (uap->nbytes < 0) return (EINVAL); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); @@ -622,7 +620,7 @@ svr4_sys_fchroot(td, uap) struct thread *td; struct svr4_sys_fchroot_args *uap; { - struct filedesc *fdp = td->td_proc->p_fd; + cap_rights_t rights; struct vnode *vp; struct file *fp; int error; @@ -630,7 +628,7 @@ svr4_sys_fchroot(td, uap) if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0) return error; /* XXX: we have the chroot priv... what cap might we need? all? */ - if ((error = getvnode(fdp, uap->fd, 0, &fp)) != 0) + if ((error = getvnode(td, uap->fd, cap_rights_init(&rights), &fp)) != 0) return error; vp = fp->f_vnode; VREF(vp); @@ -910,9 +908,7 @@ svr4_sys_ulimit(td, uap) switch (uap->cmd) { case SVR4_GFILLIM: - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512; - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_FSIZE) / 512; if (*retval == -1) *retval = 0x7fffffff; return 0; @@ -922,17 +918,13 @@ svr4_sys_ulimit(td, uap) struct rlimit krl; krl.rlim_cur = uap->newlimit * 512; - PROC_LOCK(td->td_proc); - krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE); - PROC_UNLOCK(td->td_proc); + krl.rlim_max = lim_max(td, RLIMIT_FSIZE); error = kern_setrlimit(td, RLIMIT_FSIZE, &krl); if (error) return error; - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_FSIZE); - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_FSIZE); if (*retval == -1) *retval = 0x7fffffff; return 0; @@ -943,9 +935,7 @@ svr4_sys_ulimit(td, uap) struct vmspace *vm = td->td_proc->p_vmspace; register_t r; - PROC_LOCK(td->td_proc); - r = lim_cur(td->td_proc, RLIMIT_DATA); - PROC_UNLOCK(td->td_proc); + r = lim_cur(td, RLIMIT_DATA); if (r == -1) r = 0x7fffffff; @@ -957,9 +947,7 @@ svr4_sys_ulimit(td, uap) } case SVR4_GDESLIM: - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_NOFILE); if (*retval == -1) *retval = 0x7fffffff; return 0; diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c index efa0bcf..667ee88 100644 --- a/sys/compat/svr4/svr4_resource.c +++ b/sys/compat/svr4/svr4_resource.c @@ -130,9 +130,7 @@ svr4_sys_getrlimit(td, uap) if (rl == -1) return EINVAL; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &blim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &blim); /* * Our infinity, is their maxfiles. @@ -181,9 +179,7 @@ svr4_sys_setrlimit(td, uap) if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0) return error; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &curlim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &curlim); /* * if the limit is SVR4_RLIM_INFINITY, then we set it to our @@ -228,9 +224,7 @@ svr4_sys_getrlimit64(td, uap) if (rl == -1) return EINVAL; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &blim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &blim); /* * Our infinity, is their maxfiles. @@ -279,9 +273,7 @@ svr4_sys_setrlimit64(td, uap) if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0) return error; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &curlim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &curlim); /* * if the limit is SVR4_RLIM64_INFINITY, then we set it to our diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 90fc66e..554a234 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2645,6 +2645,8 @@ device usb device udbp # USB Fm Radio device ufm +# USB temperature meter +device ugold # USB LED device uled # Human Interface Device (anything with buttons and dials) diff --git a/sys/conf/files b/sys/conf/files index aa97dde..65606b0 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -104,11 +104,12 @@ cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ cam/scsi/smp_all.c optional scbus # shared between zfs and dtrace -cddl/compat/opensolaris/kern/opensolaris.c optional zfs compile-with "${ZFS_C}" -cddl/compat/opensolaris/kern/opensolaris_cmn_err.c optional zfs compile-with "${ZFS_C}" -cddl/compat/opensolaris/kern/opensolaris_kmem.c optional zfs compile-with "${ZFS_C}" -cddl/compat/opensolaris/kern/opensolaris_misc.c optional zfs compile-with "${ZFS_C}" -cddl/compat/opensolaris/kern/opensolaris_sunddi.c optional zfs compile-with "${ZFS_C}" +cddl/compat/opensolaris/kern/opensolaris.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/compat/opensolaris/kern/opensolaris_cmn_err.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/compat/opensolaris/kern/opensolaris_kmem.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/compat/opensolaris/kern/opensolaris_misc.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/compat/opensolaris/kern/opensolaris_sunddi.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/compat/opensolaris/kern/opensolaris_taskq.c optional zfs | dtrace compile-with "${CDDL_C}" # zfs specific cddl/compat/opensolaris/kern/opensolaris_acl.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_dtrace.c optional zfs compile-with "${ZFS_C}" @@ -118,7 +119,6 @@ cddl/compat/opensolaris/kern/opensolaris_lookup.c optional zfs compile-with "$ cddl/compat/opensolaris/kern/opensolaris_policy.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_string.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_sysevent.c optional zfs compile-with "${ZFS_C}" -cddl/compat/opensolaris/kern/opensolaris_taskq.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_uio.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_vfs.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_vm.c optional zfs compile-with "${ZFS_C}" @@ -242,6 +242,17 @@ cddl/contrib/opensolaris/uts/common/zmod/trees.c optional zfs compile-with "${ cddl/contrib/opensolaris/uts/common/zmod/zmod.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/zmod_subr.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/zutil.c optional zfs compile-with "${ZFS_C}" +# dtrace specific +cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c optional dtrace compile-with "${DTRACE_C}" \ + warning "kernel contains CDDL licensed DTRACE" +cddl/dev/dtmalloc/dtmalloc.c optional dtmalloc | dtraceall compile-with "${CDDL_C}" +cddl/dev/lockstat/lockstat.c optional dtrace_lockstat | dtraceall compile-with "${CDDL_C}" +cddl/dev/profile/profile.c optional dtrace_profile | dtraceall compile-with "${CDDL_C}" +cddl/dev/sdt/sdt.c optional dtrace_sdt | dtraceall compile-with "${CDDL_C}" +cddl/dev/fbt/fbt.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" +cddl/dev/systrace/systrace.c optional dtrace_systrace | dtraceall compile-with "${CDDL_C}" +cddl/dev/prototype.c optional dtrace_prototype | dtraceall compile-with "${CDDL_C}" +fs/nfsclient/nfs_clkdtrace.c optional dtnfscl nfscl | dtraceall nfscl compile-with "${CDDL_C}" compat/freebsd32/freebsd32_capability.c optional compat_freebsd32 compat/freebsd32/freebsd32_ioctl.c optional compat_freebsd32 compat/freebsd32/freebsd32_misc.c optional compat_freebsd32 @@ -2534,6 +2545,7 @@ dev/usb/serial/usb_serial.c optional ucom | u3g | uark | ubsa | ubser | \ # dev/usb/misc/ufm.c optional ufm dev/usb/misc/udbp.c optional udbp +dev/usb/misc/ugold.c optional ugold dev/usb/misc/uled.c optional uled # # USB input drivers diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index f1a4e97..08fb59b 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -138,7 +138,12 @@ amd64/amd64/uio_machdep.c standard 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}" +cddl/contrib/opensolaris/common/atomic/amd64/opensolaris_atomic.S optional zfs | dtrace compile-with "${ZFS_S}" +cddl/dev/dtrace/amd64/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/amd64/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/x86/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" +cddl/dev/dtrace/x86/dis_tables.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" +cddl/dev/dtrace/amd64/instr_size.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" crypto/aesni/aeskeys_amd64.S optional aesni crypto/aesni/aesni.c optional aesni aesni_ghash.o optional aesni \ diff --git a/sys/conf/files.arm b/sys/conf/files.arm index a406d33..f49f4551 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -78,7 +78,10 @@ board_id.h standard \ compile-with "${AWK} -f $S/arm/conf/genboardid.awk $S/arm/conf/mach-types > board_id.h" \ no-obj no-implicit-rule before-depend \ clean "board_id.h" -cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs compile-with "${ZFS_C}" +cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/dev/dtrace/arm/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/arm/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/arm/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/fb/fb.c optional sc diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 8bdc93a..a32d8d6 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -2,6 +2,9 @@ arm/arm/devmap.c standard arm/arm/generic_timer.c standard arm/arm/pmu.c standard +arm64/acpica/acpi_machdep.c optional acpi +arm64/acpica/OsdEnvironment.c optional acpi +arm64/acpica/acpi_wakeup.c optional acpi arm64/arm64/autoconf.c standard arm64/arm64/bcopy.c standard arm64/arm64/bus_machdep.c standard @@ -20,6 +23,8 @@ arm64/arm64/dump_machdep.c standard arm64/arm64/elf_machdep.c standard arm64/arm64/exception.S standard arm64/arm64/gic.c standard +arm64/arm64/gic_acpi.c optional acpi +arm64/arm64/gic_fdt.c optional fdt arm64/arm64/gic_v3.c standard arm64/arm64/gic_v3_fdt.c optional fdt arm64/arm64/identcpu.c standard @@ -38,12 +43,15 @@ arm64/arm64/swtch.S standard arm64/arm64/sys_machdep.c standard arm64/arm64/trap.c standard arm64/arm64/uio_machdep.c standard +arm64/arm64/unwind.c optional ddb | kdtrace_hooks arm64/arm64/vfp.c standard arm64/arm64/vm_machdep.c standard +dev/acpica/acpi_if.m optional acpi dev/fdt/fdt_arm64.c optional fdt dev/hwpmc/hwpmc_arm64.c optional hwpmc dev/hwpmc/hwpmc_arm64_md.c optional hwpmc dev/ofw/ofw_cpu.c optional fdt +dev/pci/pci_host_generic.c optional pci fdt dev/psci/psci.c optional psci dev/psci/psci_arm64.S optional psci dev/uart/uart_cpu_fdt.c optional uart fdt diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 928b10d..ebfce072 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -78,7 +78,12 @@ hptrr_lib.o optional hptrr \ compile-with "uudecode < $S/dev/hptrr/i386-elf.hptrr_lib.o.uu" \ no-implicit-rule # -cddl/contrib/opensolaris/common/atomic/i386/opensolaris_atomic.S optional zfs compile-with "${ZFS_S}" +cddl/contrib/opensolaris/common/atomic/i386/opensolaris_atomic.S optional zfs | dtrace compile-with "${ZFS_S}" +cddl/dev/dtrace/i386/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/i386/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/x86/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" +cddl/dev/dtrace/x86/dis_tables.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" +cddl/dev/dtrace/i386/instr_size.c optional dtrace_fbt | dtraceall compile-with "${DTRACE_C}" compat/linprocfs/linprocfs.c optional linprocfs compat/linsysfs/linsysfs.c optional linsysfs compat/linux/linux_event.c optional compat_linux diff --git a/sys/conf/files.mips b/sys/conf/files.mips index 4bc6775a1..f476307 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -61,6 +61,8 @@ libkern/flsll.c standard libkern/memmove.c standard libkern/cmpdi2.c optional mips | mipsel libkern/ucmpdi2.c optional mips | mipsel +libkern/ashldi3.c standard +libkern/ashrdi3.c standard # cfe support dev/cfe/cfe_api.c optional cfe diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 4158f2c..167fa42 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -15,8 +15,11 @@ font.h optional sc \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" # # There is only an asm version on ppc64. -cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs powerpc compile-with "${ZFS_C}" -cddl/contrib/opensolaris/common/atomic/powerpc64/opensolaris_atomic.S optional zfs powerpc64 compile-with "${ZFS_S}" +cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs powerpc | dtrace powerpc compile-with "${ZFS_C}" +cddl/contrib/opensolaris/common/atomic/powerpc64/opensolaris_atomic.S optional zfs powerpc64 | dtrace powerpc64 compile-with "${ZFS_S}" +cddl/dev/dtrace/powerpc/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/powerpc/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/powerpc/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/bm/if_bm.c optional bm powermac diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index 8f7abaf..28ea453 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -184,11 +184,11 @@ genassym.o: $S/$M/$M/genassym.c ${SYSTEM_OBJS} genassym.o vers.o: opt_global.h -# We have "special" -I include paths for opensolaris/zfs files in 'depend'. -CFILES_NOZFS= ${CFILES:N*/opensolaris/*} -SFILES_NOZFS= ${SFILES:N*/opensolaris/*} -CFILES_ZFS= ${CFILES:M*/opensolaris/*} -SFILES_ZFS= ${SFILES:M*/opensolaris/*} +# We have "special" -I include paths for zfs/dtrace files in 'depend'. +CFILES_NOCDDL= ${CFILES:N*/cddl/*:N*fs/nfsclient/nfs_clkdtrace*} +SFILES_NOCDDL= ${SFILES:N*/cddl/*} +CFILES_CDDL= ${CFILES:M*/cddl/*} +SFILES_CDDL= ${SFILES:M*/cddl/*} kernel-depend: .depend # The argument list can be very long, so use make -V and xargs to @@ -198,13 +198,13 @@ SRCS= assym.s vnode_if.h ${BEFORE_DEPEND} ${CFILES} \ ${MFILES:T:S/.m$/.h/} .depend: .PRECIOUS ${SRCS} rm -f .newdep - ${MAKE} -V CFILES_NOZFS -V SYSTEM_CFILES -V GEN_CFILES | \ + ${MAKE} -V CFILES_NOCDDL -V SYSTEM_CFILES -V GEN_CFILES | \ MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f .newdep ${CFLAGS} - ${MAKE} -V CFILES_ZFS | \ - MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f .newdep ${ZFS_CFLAGS} - ${MAKE} -V SFILES_NOZFS | \ + ${MAKE} -V CFILES_CDDL | \ + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f .newdep ${ZFS_CFLAGS} ${FBT_CFLAGS} ${DTRACE_CFLAGS} + ${MAKE} -V SFILES_NOCDDL | \ MKDEP_CPP="${CC} -E" xargs mkdep -a -f .newdep ${ASM_CFLAGS} - ${MAKE} -V SFILES_ZFS | \ + ${MAKE} -V SFILES_CDDL | \ MKDEP_CPP="${CC} -E" xargs mkdep -a -f .newdep ${ZFS_ASM_CFLAGS} rm -f .depend mv .newdep .depend diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 8c3b9c6..3081edc 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -139,13 +139,34 @@ NORMAL_FW= uudecode -o ${.TARGET} ${.ALLSRC} NORMAL_FWO= ${LD} -b binary --no-warn-mismatch -d -warn-common -r \ -o ${.TARGET} ${.ALLSRC:M*.fw} +# Common for dtrace / zfs +CDDL_CFLAGS= -DFREEBSD_NAMECACHE -nostdinc -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S -I$S/cddl/contrib/opensolaris/common ${CFLAGS} -Wno-unknown-pragmas -Wno-missing-prototypes -Wno-undef -Wno-strict-prototypes -Wno-cast-qual -Wno-parentheses -Wno-redundant-decls -Wno-missing-braces -Wno-uninitialized -Wno-unused -Wno-inline -Wno-switch -Wno-pointer-arith -Wno-unknown-pragmas +CDDL_CFLAGS+= -include $S/cddl/compat/opensolaris/sys/debug_compat.h +CDDL_C= ${CC} -c ${CDDL_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC} + # Special flags for managing the compat compiles for ZFS -ZFS_CFLAGS= -DFREEBSD_NAMECACHE -DBUILDING_ZFS -nostdinc -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common/fs/zfs -I$S/cddl/contrib/opensolaris/uts/common/zmod -I$S/cddl/contrib/opensolaris/uts/common -I$S -I$S/cddl/contrib/opensolaris/common/zfs -I$S/cddl/contrib/opensolaris/common ${CFLAGS} -Wno-unknown-pragmas -Wno-missing-prototypes -Wno-undef -Wno-strict-prototypes -Wno-cast-qual -Wno-parentheses -Wno-redundant-decls -Wno-missing-braces -Wno-uninitialized -Wno-unused -Wno-inline -Wno-switch -Wno-pointer-arith -Wno-unknown-pragmas -ZFS_CFLAGS+= -include $S/cddl/compat/opensolaris/sys/debug_compat.h +ZFS_CFLAGS= -DBUILDING_ZFS -I$S/cddl/contrib/opensolaris/uts/common/fs/zfs -I$S/cddl/contrib/opensolaris/uts/common/zmod -I$S/cddl/contrib/opensolaris/common/zfs ${CDDL_CFLAGS} ZFS_ASM_CFLAGS= -x assembler-with-cpp -DLOCORE ${ZFS_CFLAGS} ZFS_C= ${CC} -c ${ZFS_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC} ZFS_S= ${CC} -c ${ZFS_ASM_CFLAGS} ${WERROR} ${.IMPSRC} +# Special flags for managing the compat compiles for DTrace +DTRACE_CFLAGS= -DBUILDING_DTRACE ${CDDL_CFLAGS} -I$S/cddl/dev/dtrace -I$S/cddl/dev/dtrace/${MACHINE_CPUARCH} +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" +DTRACE_CFLAGS+= -I$S/cddl/contrib/opensolaris/uts/intel -I$S/cddl/dev/dtrace/x86 +.endif +DTRACE_CFLAGS+= -I$S/cddl/contrib/opensolaris/common/util -I$S -DDIS_MEM -DSMP +DTRACE_ASM_CFLAGS= -x assembler-with-cpp -DLOCORE ${DTRACE_CFLAGS} +DTRACE_C= ${CC} -c ${DTRACE_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC} +DTRACE_S= ${CC} -c ${DTRACE_ASM_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${.IMPSRC} + +# Special flags for managing the compat compiles for DTrace/FBT +FBT_CFLAGS= -DBUILDING_DTRACE -nostdinc -I$S/cddl/dev/fbt/${MACHINE_CPUARCH} -I$S/cddl/dev/fbt -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S ${CDDL_CFLAGS} +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" +FBT_CFLAGS+= -I$S/cddl/dev/fbt/x86 +.endif +FBT_C= ${CC} -c ${FBT_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC} + .if ${MK_CTF} != "no" NORMAL_CTFCONVERT= ${CTFCONVERT} ${CTFFLAGS} ${.TARGET} .elif ${MAKE_VERSION} >= 5201111300 diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 9009745..284fe3f 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -239,7 +239,7 @@ beforedepend: ${_ILINKS} # causes all the modules to be rebuilt when the directory pointed to changes. .for _link in ${_ILINKS} .if !exists(${.OBJDIR}/${_link}) -${OBJS}: ${.OBJDIR}/${_link} +${OBJS}: ${_link} .endif .endfor @@ -253,12 +253,10 @@ SYSDIR= ${_dir} .error "can't find kernel source tree" .endif -.for _link in ${_ILINKS} -.PHONY: ${_link} -${_link}: ${.OBJDIR}/${_link} +.NOPATH: ${_ILINKS} -${.OBJDIR}/${_link}: - @case ${.TARGET:T} in \ +${_ILINKS}: + @case ${.TARGET} in \ machine) \ path=${SYSDIR}/${MACHINE}/include ;; \ *) \ @@ -267,7 +265,6 @@ ${.OBJDIR}/${_link}: path=`(cd $$path && /bin/pwd)` ; \ ${ECHO} ${.TARGET:T} "->" $$path ; \ ln -sf $$path ${.TARGET:T} -.endfor CLEANFILES+= ${PROG} ${KMOD}.kld ${OBJS} diff --git a/sys/contrib/dev/acpica/acpica_prep.sh b/sys/contrib/dev/acpica/acpica_prep.sh index faf850e..e6bf575 100755 --- a/sys/contrib/dev/acpica/acpica_prep.sh +++ b/sys/contrib/dev/acpica/acpica_prep.sh @@ -19,20 +19,20 @@ fulldirs="common compiler components include os_specific" # files to remove stripdirs="generate libraries tests tools" stripfiles="Makefile README accygwin.h acdragonfly.h acdragonflyex.h \ - acefi.h achaiku.h acintel.h aclinux.h aclinuxex.h acmacosx.h \ - acmsvc.h acnetbsd.h acos2.h acwin.h acwin64.h new_table.txt \ - osbsdtbl.c osefitbl.c osefixf.c osfreebsdtbl.c oslinuxtbl.c \ - osunixdir.c osunixmap.c oswindir.c oswintbl.c oswinxf.c \ - readme.txt utclib.c" + acefi.h acefiex.h achaiku.h acintel.h aclinux.h aclinuxex.h \ + acmacosx.h acmsvc.h acnetbsd.h acos2.h acwin.h acwin64.h \ + new_table.txt osbsdtbl.c osefitbl.c osefixf.c osfreebsdtbl.c \ + oslinuxtbl.c osunixdir.c osunixmap.c oswindir.c oswintbl.c \ + oswinxf.c readme.txt utclib.c" # include files to canonify -src_headers="acapps.h acbuffer.h accommon.h acconfig.h acdebug.h \ - acdisasm.h acdispat.h acevents.h acexcep.h acglobal.h achware.h \ - acinterp.h aclocal.h acmacros.h acnames.h acnamesp.h acobject.h \ - acopcode.h acoutput.h acparser.h acpi.h acpiosxf.h acpixf.h \ - acpredef.h acresrc.h acrestyp.h acstruct.h actables.h actbl.h \ - actbl1.h actbl2.h actbl3.h actypes.h acutils.h amlcode.h \ - amlresrc.h platform/acenv.h platform/acenvex.h \ +src_headers="acapps.h acbuffer.h acclib.h accommon.h acconfig.h \ + acdebug.h acdisasm.h acdispat.h acevents.h acexcep.h acglobal.h \ + achware.h acinterp.h aclocal.h acmacros.h acnames.h acnamesp.h \ + acobject.h acopcode.h acoutput.h acparser.h acpi.h acpiosxf.h \ + acpixf.h acpredef.h acresrc.h acrestyp.h acstruct.h actables.h \ + actbl.h actbl1.h actbl2.h actbl3.h actypes.h acutils.h acuuid.h \ + amlcode.h amlresrc.h platform/acenv.h platform/acenvex.h \ platform/acfreebsd.h platform/acgcc.h" comp_headers="aslcompiler.h asldefine.h aslglobal.h aslmessages.h \ aslsupport.l asltypes.h dtcompiler.h dttemplate.h preprocess.h" diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt index 511652f..9abe735 100644 --- a/sys/contrib/dev/acpica/changes.txt +++ b/sys/contrib/dev/acpica/changes.txt @@ -1,5 +1,130 @@ ---------------------------------------- -08 April 2015. Summary of changes for version 20150515: +19 June 2015. Summary of changes for version 20150619: + +Two regressions in version 20150616 have been addressed: + +Fixes some problems/issues with the C library macro removal (ACPI_STRLEN, +etc.) This update changes ACPICA to only use the standard headers for +functions, or the prototypes for the local versions of the C library +functions. Across the source code, this required some additional casts +for some Clib invocations for portability. Moved all local prototypes to +a new file, acclib.h + +Fixes several problems with recent changes to the handling of the FACS +table that could cause some systems not to boot. + + +---------------------------------------- +16 June 2015. Summary of changes for version 20150616: + + +1) ACPICA kernel-resident subsystem: + +Across the entire ACPICA source code base, the various macros for the C +library functions (such as ACPI_STRLEN, etc.) have been removed and +replaced by the standard C library names (strlen, etc.) The original +purpose for these macros is no longer applicable. This simplification +reduces the number of macros used in the ACPICA source code +significantly, improving readability and maintainability. + +Implemented support for a new ACPI table, the OSDT. This table, the +"override" SDT, can be loaded directly by the host OS at boot time. It +enables the replacement of existing namespace objects that were installed +via the DSDT and/or SSDTs. The primary purpose for this is to replace +buggy or incorrect ASL/AML code obtained via the BIOS. The OSDT is slated +for inclusion in a future version of the ACPI Specification. Lv Zheng/Bob +Moore. + +Added support for systems with (improperly) two FACS tables -- a "32-bit" +table (via FADT 32-bit legacy field) and a "64-bit" table (via the 64-bit +X field). This change will support both automatically. There continues to +be systems found with this issue. This support requires a change to the +AcpiSetFirmwareWakingVector interface. Also, a public global variable has +been added to allow the host to select which FACS is desired +(AcpiGbl_Use32BitFacsAddresses). See the ACPICA reference for more +details Lv Zheng. + +Added a new feature to allow for systems that do not contain an FACS. +Although this is already supported on hardware-reduced platforms, the +feature has been extended for all platforms. The reasoning is that we do +not want to abort the entire ACPICA initialization just because the +system is seriously buggy and has no FACS. + +Fixed a problem where the GUID strings for NFIT tables (in acuuid.h) were +not correctly transcribed from the ACPI specification in ACPICA version +20150515. + +Implemented support for the _CLS object in the AcpiGetObjectInfo external +interface. + +Updated the definitions of the TCPA and TPM2 ACPI tables to the more +recent TCG ACPI Specification, December 14, 2014. Table disassembler and +compiler also updated. Note: The TCPA "server" table is not supported by +the disassembler/table-compiler at this time. + +ACPI 6.0: Added definitions for the new GIC version field in the MADT. + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The +debug version of the code includes the debug output trace mechanism and +has a much larger code and data size. + + Current Release: + Non-Debug Version: 100.6K Code, 27.6K Data, 128.2K Total + Debug Version: 196.2K Code, 81.0K Data, 277.2K Total + Previous Release: + Non-Debug Version: 99.9K Code, 27.5K Data, 127.4K Total + Debug Version: 195.2K Code, 80.8K Data, 276.0K Total + + +2) iASL Compiler/Disassembler and Tools: + +Disassembler: Fixed a problem with the new symbolic operator disassembler +where incorrect ASL code could be emitted in some cases for the "non- +commutative" operators -- Subtract, Divide, Modulo, ShiftLeft, and +ShiftRight. The actual problem cases seem to be rather unusual in common +ASL code, however. David Box. + +Modified the linux version of acpidump to obtain ACPI tables from not +just /dev/mem (which may not exist) and /sys/firmware/acpi/tables. Lv +Zheng. + +iASL: Fixed a problem where the user preprocessor output file (.i) +contained extra data that was not expected. The compiler was using this +file as a temporary file and passed through #line directives in order to +keep compiler error messages in sync with the input file and line number +across multiple include files. The (.i) is no longer a temporary file as +the compiler uses a new, different file for the original purpose. + +iASL: Fixed a problem where comments within the original ASL source code +file were not passed through to the preprocessor output file, nor any +listing files. + +iASL: Fixed some issues for the handling of the "#include" preprocessor +directive and the similar (but not the same) "Include" ASL operator. + +iASL: Add support for the new OSDT in both the disassembler and compiler. + +iASL: Fixed a problem with the constant folding support where a Buffer +object could be incorrectly generated (incorrectly formed) during a +conversion to a Store() operator. + +AcpiHelp: Updated for new NFIT GUIDs, "External" AML opcode, and new +description text for the _REV predefined name. _REV now permanently +returns 2, as per the ACPI 6.0 specification. + +Debugger: Enhanced the output of the Debug ASL object for references +produced by the Index operator. For Buffers and strings, only output the +actual byte pointed to by the index. For packages, only print the single +package element decoded by the index. Previously, the entire +buffer/string/package was emitted. + +iASL/Table-compiler: Fixed a regression where the "generic" data types +were no longer recognized, causing errors. + + +---------------------------------------- +15 May 2015. Summary of changes for version 20150515: This release implements most of ACPI 6.0 as described below. @@ -34,7 +159,7 @@ iASL disassembler and table compiler: Added ACPI 6.0 changes to existing tables: FADT, MADT. iASL preprocessor: Added a new directive to enable inclusion of binary -blobs into ASL code. The new directive is #includebinary. It takes a +blobs into ASL code. The new directive is #includebuffer. It takes a binary file as input and emits a named ascii buffer object into the ASL code. diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c index 5d0cee2..5942476 100644 --- a/sys/contrib/dev/acpica/common/adisasm.c +++ b/sys/contrib/dev/acpica/common/adisasm.c @@ -243,7 +243,7 @@ AdAmlDisassemble ( while (ExternalFileList) { ExternalFilename = ExternalFileList->Path; - if (!ACPI_STRCMP (ExternalFilename, Filename)) + if (!strcmp (ExternalFilename, Filename)) { /* Next external file */ diff --git a/sys/contrib/dev/acpica/common/ahids.c b/sys/contrib/dev/acpica/common/ahids.c index 038d9f6..1af6b41 100644 --- a/sys/contrib/dev/acpica/common/ahids.c +++ b/sys/contrib/dev/acpica/common/ahids.c @@ -230,7 +230,7 @@ AcpiAhMatchHardwareId ( for (Info = AslDeviceIds; Info->Name; Info++) { - if (!ACPI_STRCMP (HardwareId, Info->Name)) + if (!strcmp (HardwareId, Info->Name)) { return (Info); } diff --git a/sys/contrib/dev/acpica/common/ahpredef.c b/sys/contrib/dev/acpica/common/ahpredef.c index 1454880..3026ce3 100644 --- a/sys/contrib/dev/acpica/common/ahpredef.c +++ b/sys/contrib/dev/acpica/common/ahpredef.c @@ -249,7 +249,7 @@ const AH_PREDEFINED_NAME AslPredefinedInfo[] = AH_PREDEF ("_RBW", "Register Bit Width", "Resource Descriptor field"), AH_PREDEF ("_RDI", "Resource Dependencies for Idle", "Returns a list of dependencies for idle states"), AH_PREDEF ("_REG", "Region Availability", "Inform AML code of an operation region availability change"), - AH_PREDEF ("_REV", "Supported ACPI Revision", "Returns the revision of the ACPI specification that is implemented"), + AH_PREDEF ("_REV", "Supported Integer Width", "Returns the supported integer width (<= 1: 32 bits only, >=2: both 32 and 64 bits"), AH_PREDEF ("_RMV", "Removal Status", "Returns a device's removal ability status (docking)"), AH_PREDEF ("_RNG", "Range", "Memory range type, Resource Descriptor field"), AH_PREDEF ("_RST", "Device Reset", "Executes a reset on a device"), diff --git a/sys/contrib/dev/acpica/common/ahuuids.c b/sys/contrib/dev/acpica/common/ahuuids.c index eeec8b8..46b52eb 100644 --- a/sys/contrib/dev/acpica/common/ahuuids.c +++ b/sys/contrib/dev/acpica/common/ahuuids.c @@ -122,7 +122,7 @@ AcpiAhMatchUuid ( AcpiUtConvertStringToUuid (Info->String, UuidBuffer); - if (!ACPI_MEMCMP (Data, UuidBuffer, UUID_BUFFER_LENGTH)) + if (!memcmp (Data, UuidBuffer, UUID_BUFFER_LENGTH)) { return (Info->Description); } diff --git a/sys/contrib/dev/acpica/common/dmextern.c b/sys/contrib/dev/acpica/common/dmextern.c index 2ea54ad..22d54e9 100644 --- a/sys/contrib/dev/acpica/common/dmextern.c +++ b/sys/contrib/dev/acpica/common/dmextern.c @@ -224,7 +224,7 @@ AcpiDmNormalizeParentPrefix ( return (NULL); } - Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1); + Length = (strlen (ParentPath) + strlen (Path) + 1); if (ParentPath[1]) { /* @@ -253,7 +253,7 @@ AcpiDmNormalizeParentPrefix ( * * Copy the parent path */ - ACPI_STRCPY (Fullpath, &ParentPath[Index]); + strcpy (Fullpath, &ParentPath[Index]); /* * Add dot separator @@ -261,12 +261,12 @@ AcpiDmNormalizeParentPrefix ( */ if (ParentPath[1]) { - ACPI_STRCAT (Fullpath, "."); + strcat (Fullpath, "."); } /* Copy child path (carat parent prefix(es) were skipped above) */ - ACPI_STRCAT (Fullpath, Path); + strcat (Fullpath, Path); Cleanup: ACPI_FREE (ParentPath); @@ -648,13 +648,13 @@ AcpiDmAddNodeToExternalList ( if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1])) { - Temp = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (ExternalPath) + 1); + Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1); if (!Temp) { return_VOID; } - ACPI_STRCPY (Temp, &ExternalPath[1]); + strcpy (Temp, &ExternalPath[1]); ACPI_FREE (ExternalPath); ExternalPath = Temp; } @@ -806,7 +806,7 @@ AcpiDmCreateNewExternal ( NextExternal = AcpiGbl_ExternalList; while (NextExternal) { - if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) + if (!strcmp (ExternalPath, NextExternal->Path)) { /* Duplicate method, check that the Value (ArgCount) is the same */ @@ -849,7 +849,7 @@ AcpiDmCreateNewExternal ( NewExternal->Value = Value; NewExternal->Path = ExternalPath; NewExternal->Type = Type; - NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); + NewExternal->Length = (UINT16) strlen (ExternalPath); NewExternal->InternalPath = InternalPath; /* Link the new descriptor into the global list, alphabetically ordered */ diff --git a/sys/contrib/dev/acpica/common/dmrestag.c b/sys/contrib/dev/acpica/common/dmrestag.c index c457658..4296039 100644 --- a/sys/contrib/dev/acpica/common/dmrestag.c +++ b/sys/contrib/dev/acpica/common/dmrestag.c @@ -679,10 +679,10 @@ AcpiGetTagPathname ( * end up in the final compiled AML, it's just an appearance issue for the * disassembled code. */ - Pathname[ACPI_STRLEN (Pathname) - ACPI_NAME_SIZE] = 0; - ACPI_STRNCAT (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE); - ACPI_STRCAT (Pathname, "."); - ACPI_STRNCAT (Pathname, Tag, ACPI_NAME_SIZE); + Pathname[strlen (Pathname) - ACPI_NAME_SIZE] = 0; + strncat (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE); + strcat (Pathname, "."); + strncat (Pathname, Tag, ACPI_NAME_SIZE); /* Internalize the namepath to AML format */ diff --git a/sys/contrib/dev/acpica/common/dmtable.c b/sys/contrib/dev/acpica/common/dmtable.c index 3820c94..0b1f68e 100644 --- a/sys/contrib/dev/acpica/common/dmtable.c +++ b/sys/contrib/dev/acpica/common/dmtable.c @@ -528,7 +528,7 @@ AcpiDmDumpDataTable ( TableData = AcpiDmGetTableData (Table->Signature); if (!TableData) { - if (!ACPI_STRNCMP (Table->Signature, "OEM", 3)) + if (!strncmp (Table->Signature, "OEM", 3)) { AcpiOsPrintf ("\n**** OEM-defined ACPI table [%4.4s], unknown contents\n\n", Table->Signature); @@ -856,7 +856,7 @@ AcpiDmDumpTable ( case ACPI_DMT_STRING: - ByteLength = ACPI_STRLEN (ACPI_CAST_PTR (char, Target)) + 1; + ByteLength = strlen (ACPI_CAST_PTR (char, Target)) + 1; break; case ACPI_DMT_GAS: diff --git a/sys/contrib/dev/acpica/common/dmtbdump.c b/sys/contrib/dev/acpica/common/dmtbdump.c index 94358e8..67d0f1c 100644 --- a/sys/contrib/dev/acpica/common/dmtbdump.c +++ b/sys/contrib/dev/acpica/common/dmtbdump.c @@ -155,7 +155,7 @@ AcpiDmDumpUnicode ( for (i = 0; i < Length; i += 2) { - if (!ACPI_IS_PRINT (Buffer[i])) + if (!isprint (Buffer[i])) { goto DumpRawBuffer; } @@ -1701,7 +1701,7 @@ AcpiDmDumpIort ( InfoTable = AcpiDmTableInfoIort1; Length = ACPI_OFFSET (ACPI_IORT_NAMED_COMPONENT, DeviceName); String = ACPI_ADD_PTR (char, IortNode, NodeOffset + Length); - Length += ACPI_STRLEN (String) + 1; + Length += strlen (String) + 1; break; case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: @@ -3344,7 +3344,7 @@ AcpiDmDumpStao ( while (Offset < Table->Length) { Namepath = ACPI_ADD_PTR (char, Table, Offset); - StringLength = ACPI_STRLEN (Namepath) + 1; + StringLength = strlen (Namepath) + 1; AcpiDmLineHeader (Offset, StringLength, "Namestring"); AcpiOsPrintf ("\"%s\"\n", Namepath); diff --git a/sys/contrib/dev/acpica/common/dmtbinfo.c b/sys/contrib/dev/acpica/common/dmtbinfo.c index a803c70..af67d43 100644 --- a/sys/contrib/dev/acpica/common/dmtbinfo.c +++ b/sys/contrib/dev/acpica/common/dmtbinfo.c @@ -113,7 +113,7 @@ #define ACPI_SPMI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPMI,f) #define ACPI_SRAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SRAT,f) #define ACPI_STAO_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_STAO,f) -#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA,f) +#define ACPI_TCPA_CLIENT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_CLIENT,f) #define ACPI_TPM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM2,f) #define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f) #define ACPI_WAET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WAET,f) @@ -2611,15 +2611,15 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoStaoStr[] = /******************************************************************************* * - * TCPA - Trusted Computing Platform Alliance table + * TCPA - Trusted Computing Platform Alliance table (Client) * ******************************************************************************/ ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] = { - {ACPI_DMT_UINT16, ACPI_TCPA_OFFSET (Reserved), "Reserved", 0}, - {ACPI_DMT_UINT32, ACPI_TCPA_OFFSET (MaxLogLength), "Max Event Log Length", 0}, - {ACPI_DMT_UINT64, ACPI_TCPA_OFFSET (LogAddress), "Event Log Address", 0}, + {ACPI_DMT_UINT16, ACPI_TCPA_CLIENT_OFFSET (PlatformClass), "Platform Class", 0}, + {ACPI_DMT_UINT32, ACPI_TCPA_CLIENT_OFFSET (MinimumLogLength), "Min Event Log Length", 0}, + {ACPI_DMT_UINT64, ACPI_TCPA_CLIENT_OFFSET (LogAddress), "Event Log Address", 0}, ACPI_DMT_TERMINATOR }; @@ -2632,7 +2632,8 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] = ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[] = { - {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (Flags), "Flags", 0}, + {ACPI_DMT_UINT16, ACPI_TPM2_OFFSET (PlatformClass), "Platform Class", 0}, + {ACPI_DMT_UINT16, ACPI_TPM2_OFFSET (Reserved), "Reserved", 0}, {ACPI_DMT_UINT64, ACPI_TPM2_OFFSET (ControlAddress), "Control Address", 0}, {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (StartMethod), "Start Method", 0}, ACPI_DMT_TERMINATOR diff --git a/sys/contrib/dev/acpica/common/getopt.c b/sys/contrib/dev/acpica/common/getopt.c index b93156c..4a199c0 100644 --- a/sys/contrib/dev/acpica/common/getopt.c +++ b/sys/contrib/dev/acpica/common/getopt.c @@ -145,7 +145,7 @@ AcpiGetopt( { return (ACPI_OPT_END); } - else if (ACPI_STRCMP (argv[AcpiGbl_Optind], "--") == 0) + else if (strcmp (argv[AcpiGbl_Optind], "--") == 0) { AcpiGbl_Optind++; return (ACPI_OPT_END); @@ -159,7 +159,7 @@ AcpiGetopt( /* Make sure that the option is legal */ if (CurrentChar == ':' || - (OptsPtr = ACPI_STRCHR (opts, CurrentChar)) == NULL) + (OptsPtr = strchr (opts, CurrentChar)) == NULL) { ACPI_OPTION_ERROR ("Illegal option: -", CurrentChar); diff --git a/sys/contrib/dev/acpica/compiler/aslanalyze.c b/sys/contrib/dev/acpica/compiler/aslanalyze.c index 3c3eee8..e9b6fb2 100644 --- a/sys/contrib/dev/acpica/compiler/aslanalyze.c +++ b/sys/contrib/dev/acpica/compiler/aslanalyze.c @@ -67,8 +67,8 @@ AnIsInternalMethod ( ACPI_PARSE_OBJECT *Op) { - if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) || - (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI"))) + if ((!strcmp (Op->Asl.ExternalName, "\\_OSI")) || + (!strcmp (Op->Asl.ExternalName, "_OSI"))) { return (TRUE); } @@ -94,8 +94,8 @@ AnGetInternalMethodReturnType ( ACPI_PARSE_OBJECT *Op) { - if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) || - (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI"))) + if ((!strcmp (Op->Asl.ExternalName, "\\_OSI")) || + (!strcmp (Op->Asl.ExternalName, "_OSI"))) { return (ACPI_BTYPE_STRING); } @@ -462,7 +462,7 @@ ApCheckForGpeNameConflict ( /* Verify 3rd/4th chars are a valid hex value */ - GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); + GpeNumber = strtoul (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) { return; diff --git a/sys/contrib/dev/acpica/compiler/aslascii.c b/sys/contrib/dev/acpica/compiler/aslascii.c index 08e4630..1583dc3 100644 --- a/sys/contrib/dev/acpica/compiler/aslascii.c +++ b/sys/contrib/dev/acpica/compiler/aslascii.c @@ -226,7 +226,7 @@ FlCheckForAscii ( /* Ensure character is either printable or a "space" char */ - else if (!ACPI_IS_PRINT (Byte) && !ACPI_IS_SPACE (Byte)) + else if (!isprint (Byte) && !isspace (Byte)) { if ((BadBytes < 10) && (DisplayErrors)) { diff --git a/sys/contrib/dev/acpica/compiler/aslcodegen.c b/sys/contrib/dev/acpica/compiler/aslcodegen.c index 8dd30f3..a01afb7 100644 --- a/sys/contrib/dev/acpica/compiler/aslcodegen.c +++ b/sys/contrib/dev/acpica/compiler/aslcodegen.c @@ -110,7 +110,7 @@ CgGenerateAmlOutput ( DbgPrint (ASL_TREE_OUTPUT, "%*s Value P_Op A_Op OpLen PByts Len SubLen PSubLen OpPtr" - " Parent Child Next Flags AcTyp Final Col L\n", + " Parent Child Next Flags AcTyp Final Col L# EL# LL# ELL#\n", 76, " "); CgCloseTable (); @@ -145,7 +145,7 @@ CgAmlWriteWalk ( "Final parse tree used for AML output:\n"); DbgPrint (ASL_TREE_OUTPUT, "%*s Value P_Op A_Op OpLen PByts Len SubLen PSubLen OpPtr" - " Parent Child Next Flags AcTyp Final Col L\n", + " Parent Child Next Flags AcTyp Final Col L# EL# LL# ELL#\n", 76, " "); } @@ -169,7 +169,7 @@ CgAmlWriteWalk ( DbgPrint (ASL_TREE_OUTPUT, "%08X %04X %04X %01X %04X %04X %04X %04X " - "%08X %08X %08X %08X %08X %08X %04X %02d %02d\n", + "%08X %08X %08X %08X %08X %08X %04X %02d %02d %02d %02d %02d\n", /* 1 */ (UINT32) Op->Asl.Value.Integer, /* 2 */ Op->Asl.ParseOpcode, /* 3 */ Op->Asl.AmlOpcode, @@ -186,7 +186,10 @@ CgAmlWriteWalk ( /* 14 */ Op->Asl.AcpiBtype, /* 15 */ Op->Asl.FinalAmlLength, /* 16 */ Op->Asl.Column, - /* 17 */ Op->Asl.LineNumber); + /* 17 */ Op->Asl.LineNumber, + /* 18 */ Op->Asl.EndLine, + /* 19 */ Op->Asl.LogicalLineNumber, + /* 20 */ Op->Asl.EndLogicalLine); /* Generate the AML for this node */ diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c index 0b0ca7a..9aaac3b 100644 --- a/sys/contrib/dev/acpica/compiler/aslcompile.c +++ b/sys/contrib/dev/acpica/compiler/aslcompile.c @@ -103,6 +103,9 @@ CmDoCompile ( /* Preprocessor */ PrDoPreprocess (); + Gbl_CurrentLineNumber = 1; + Gbl_LogicalLineNumber = 1; + if (Gbl_PreprocessOnly) { UtEndEvent (Event); @@ -112,6 +115,7 @@ CmDoCompile ( } UtEndEvent (Event); + /* Build the parse tree */ Event = UtBeginEvent ("Parse source code and build parse tree"); @@ -708,7 +712,7 @@ CmCleanupAndExit ( /* Close all open files */ /* - * Take care with the preprocessor file (.i), it might be the same + * Take care with the preprocessor file (.pre), it might be the same * as the "input" file, depending on where the compiler has terminated * or aborted. Prevent attempt to close the same file twice in * loop below. @@ -733,10 +737,9 @@ CmCleanupAndExit ( FlDeleteFile (ASL_FILE_AML_OUTPUT); } - /* Delete the preprocessor output file (.i) unless -li flag is set */ + /* Delete the preprocessor temp file unless full debug was specified */ - if (!Gbl_PreprocessorOutputFlag && - Gbl_PreprocessFlag) + if (Gbl_PreprocessFlag && !Gbl_KeepPreprocessorTempFile) { FlDeleteFile (ASL_FILE_PREPROCESSOR); } @@ -752,8 +755,6 @@ CmCleanupAndExit ( * Note: Handles are cleared by FlCloseFile above, so we look at the * filename instead, to determine if the .SRC file was actually * created. - * - * TBD: SourceOutput should be .TMP, then rename if we want to keep it? */ if (!Gbl_SourceOutputFlag) { diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.h b/sys/contrib/dev/acpica/compiler/aslcompiler.h index 181b36c..f84f988 100644 --- a/sys/contrib/dev/acpica/compiler/aslcompiler.h +++ b/sys/contrib/dev/acpica/compiler/aslcompiler.h @@ -1003,7 +1003,7 @@ UtDoConstant ( char *String); ACPI_STATUS -UtStrtoul64 ( +stroul64 ( char *String, UINT32 Base, UINT64 *RetInteger); diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.l b/sys/contrib/dev/acpica/compiler/aslcompiler.l index 621f5ae..6a3541b 100644 --- a/sys/contrib/dev/acpica/compiler/aslcompiler.l +++ b/sys/contrib/dev/acpica/compiler/aslcompiler.l @@ -709,7 +709,7 @@ NamePathTail [.]{NameSeg} return (PARSEOP_NAMESTRING); } . { count (1); - if (ACPI_IS_PRINT (*AslCompilertext)) + if (isprint ((int) *AslCompilertext)) { sprintf (MsgBuffer, "Invalid character (%c), expecting ASL keyword or name", diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h index 0697276..0b5f614 100644 --- a/sys/contrib/dev/acpica/compiler/asldefine.h +++ b/sys/contrib/dev/acpica/compiler/asldefine.h @@ -105,7 +105,8 @@ /* filename suffixes for output files */ -#define FILE_SUFFIX_PREPROCESSOR "i" +#define FILE_SUFFIX_PREPROC_USER "i " +#define FILE_SUFFIX_PREPROCESSOR "pre" #define FILE_SUFFIX_AML_CODE "aml" #define FILE_SUFFIX_MAP "map" #define FILE_SUFFIX_LISTING "lst" @@ -136,6 +137,8 @@ #define ASL_ABORT TRUE #define ASL_NO_ABORT FALSE #define ASL_EOF ACPI_UINT32_MAX +#define ASL_WITHIN_COMMENT (ACPI_UINT32_MAX -1) +#define ASL_BLANK_LINE (ACPI_UINT32_MAX -1) /* Listings */ diff --git a/sys/contrib/dev/acpica/compiler/aslerror.c b/sys/contrib/dev/acpica/compiler/aslerror.c index 9b8928c..870e30b 100644 --- a/sys/contrib/dev/acpica/compiler/aslerror.c +++ b/sys/contrib/dev/acpica/compiler/aslerror.c @@ -561,11 +561,11 @@ AslCommonError2 ( /* Keep a copy of the extra message */ - ACPI_STRCPY (MessageBuffer, ExtraMessage); + strcpy (MessageBuffer, ExtraMessage); } LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1); - ACPI_STRCPY (LineBuffer, SourceLine); + strcpy (LineBuffer, SourceLine); /* Initialize the error node */ @@ -647,7 +647,7 @@ AslCommonError ( /* Keep a copy of the extra message */ - ACPI_STRCPY (MessageBuffer, ExtraMessage); + strcpy (MessageBuffer, ExtraMessage); } /* Initialize the error node */ diff --git a/sys/contrib/dev/acpica/compiler/aslfileio.c b/sys/contrib/dev/acpica/compiler/aslfileio.c index cf726dd..3feb8ea 100644 --- a/sys/contrib/dev/acpica/compiler/aslfileio.c +++ b/sys/contrib/dev/acpica/compiler/aslfileio.c @@ -218,6 +218,19 @@ FlWriteFile ( FlFileError (FileId, ASL_MSG_WRITE); AslAbort (); } + + if ((FileId == ASL_FILE_PREPROCESSOR) && Gbl_PreprocessorOutputFlag) + { + /* Duplicate the output to the user preprocessor (.i) file */ + + Actual = fwrite ((char *) Buffer, 1, Length, + Gbl_Files[ASL_FILE_PREPROCESSOR_USER].Handle); + if (Actual != Length) + { + FlFileError (FileId, ASL_MSG_WRITE); + AslAbort (); + } + } } @@ -247,7 +260,6 @@ FlPrintFile ( va_start (Args, Format); - Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args); va_end (Args); @@ -256,6 +268,30 @@ FlPrintFile ( FlFileError (FileId, ASL_MSG_WRITE); AslAbort (); } + + if ((FileId == ASL_FILE_PREPROCESSOR) && Gbl_PreprocessorOutputFlag) + { + /* + * Duplicate the output to the user preprocessor (.i) file, + * except: no #line directives. + */ + if (!strncmp (Format, "#line", 5)) + { + return; + } + + va_start (Args, Format); + Actual = vfprintf (Gbl_Files[ASL_FILE_PREPROCESSOR_USER].Handle, + Format, Args); + va_end (Args); + + if (Actual == -1) + { + FlFileError (FileId, ASL_MSG_WRITE); + AslAbort (); + } + } + } diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c index d8c9ed5..37043cb 100644 --- a/sys/contrib/dev/acpica/compiler/aslfiles.c +++ b/sys/contrib/dev/acpica/compiler/aslfiles.c @@ -43,6 +43,7 @@ #include <contrib/dev/acpica/compiler/aslcompiler.h> #include <contrib/dev/acpica/include/acapps.h> +#include <contrib/dev/acpica/compiler/dtcompiler.h> #define _COMPONENT ACPI_COMPILER ACPI_MODULE_NAME ("aslfiles") @@ -84,7 +85,6 @@ FlSetLineNumber ( LineNumber, Gbl_LogicalLineNumber); Gbl_CurrentLineNumber = LineNumber; - Gbl_LogicalLineNumber = LineNumber; } @@ -303,6 +303,7 @@ FlOpenIncludeWithPrefix ( { FILE *IncludeFile; char *Pathname; + UINT32 OriginalLineNumber; /* Build the full pathname to the file */ @@ -322,13 +323,20 @@ FlOpenIncludeWithPrefix ( return (NULL); } -#ifdef _MUST_HANDLE_COMMENTS /* - * Check entire include file for any # preprocessor directives. + * Check the entire include file for any # preprocessor directives. * This is because there may be some confusion between the #include - * preprocessor directive and the ASL Include statement. + * preprocessor directive and the ASL Include statement. A file included + * by the ASL include cannot contain preprocessor directives because + * the preprocessor has already run by the time the ASL include is + * recognized (by the compiler, not the preprocessor.) + * + * Note: DtGetNextLine strips/ignores comments. + * Save current line number since DtGetNextLine modifies it. */ - while (fgets (Gbl_CurrentLineBuffer, Gbl_LineBufferSize, IncludeFile)) + Gbl_CurrentLineNumber--; + OriginalLineNumber = Gbl_CurrentLineNumber; + while (DtGetNextLine (IncludeFile, DT_ALLOW_MULTILINE_QUOTES) != ASL_EOF) { if (Gbl_CurrentLineBuffer[0] == '#') { @@ -336,7 +344,7 @@ FlOpenIncludeWithPrefix ( Op, "use #include instead"); } } -#endif + Gbl_CurrentLineNumber = OriginalLineNumber; /* Must seek back to the start of the file */ @@ -579,8 +587,6 @@ FlOpenMiscOutputFiles ( /* Open the debug file as STDERR, text mode */ - /* TBD: hide this behind a FlReopenFile function */ - Gbl_Files[ASL_FILE_DEBUG_OUTPUT].Filename = Filename; Gbl_Files[ASL_FILE_DEBUG_OUTPUT].Handle = freopen (Filename, "w+t", stderr); @@ -588,13 +594,15 @@ FlOpenMiscOutputFiles ( if (!Gbl_Files[ASL_FILE_DEBUG_OUTPUT].Handle) { /* - * A problem with freopen is that on error, - * we no longer have stderr. + * A problem with freopen is that on error, we no longer + * have stderr and cannot emit normal error messages. + * Emit error to stdout, close files, and exit. */ - Gbl_DebugFlag = FALSE; - memcpy (stderr, stdout, sizeof (FILE)); - FlFileError (ASL_FILE_DEBUG_OUTPUT, ASL_MSG_DEBUG_FILENAME); - AslAbort (); + fprintf (stdout, + "\nCould not open debug output file: %s\n\n", Filename); + + CmCleanupAndExit (); + exit (1); } AslCompilerSignon (ASL_FILE_DEBUG_OUTPUT); @@ -621,7 +629,7 @@ FlOpenMiscOutputFiles ( AslCompilerFileHeader (ASL_FILE_LISTING_OUTPUT); } - /* Create the preprocessor output file if preprocessor enabled */ + /* Create the preprocessor output temp file if preprocessor enabled */ if (Gbl_PreprocessFlag) { @@ -636,6 +644,23 @@ FlOpenMiscOutputFiles ( FlOpenFile (ASL_FILE_PREPROCESSOR, Filename, "w+t"); } + /* + * Create the "user" preprocessor output file if -li flag set. + * Note, this file contains no embedded #line directives. + */ + if (Gbl_PreprocessorOutputFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_PREPROC_USER); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_PREPROCESSOR_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + FlOpenFile (ASL_FILE_PREPROCESSOR_USER, Filename, "w+t"); + } + /* All done for data table compiler */ if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) diff --git a/sys/contrib/dev/acpica/compiler/aslfold.c b/sys/contrib/dev/acpica/compiler/aslfold.c index 26b786d..af7a019 100644 --- a/sys/contrib/dev/acpica/compiler/aslfold.c +++ b/sys/contrib/dev/acpica/compiler/aslfold.c @@ -236,6 +236,8 @@ OpcAmlCheckForConstant ( */ if (WalkState->Opcode == AML_BUFFER_OP) { + DbgPrint (ASL_PARSE_OUTPUT, + "\nBuffer+Buffer->Buffer constant reduction is not supported yet"); Status = AE_TYPE; goto CleanupAndExit; } @@ -380,10 +382,12 @@ TrSimpleConstantReduction ( return (Status); } + /* Disconnect any existing children, install new constant */ + + Op->Asl.Child = NULL; TrInstallReducedConstant (Op, ObjDesc); UtSetParseOpName (Op); - Op->Asl.Child = NULL; return (AE_OK); } @@ -494,6 +498,10 @@ TrTransformToStoreOp ( goto EvalError; } + /* Truncate any subtree expressions, they have been evaluated */ + + Child1->Asl.Child = NULL; + /* Folded constant is in ObjDesc, store into Child1 */ TrInstallReducedConstant (Child1, ObjDesc); @@ -505,11 +513,6 @@ TrTransformToStoreOp ( UtSetParseOpName (Op); Op->Common.Parent = OriginalParent; - /* Truncate any subtree expressions, they have been evaluated */ - - Child1->Asl.Child = NULL; - Child2->Asl.Child = NULL; - /* First child is the folded constant */ /* Second child will be the target */ @@ -547,7 +550,8 @@ TrInstallReducedConstant ( ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT *ObjDesc) { - ACPI_PARSE_OBJECT *RootOp; + ACPI_PARSE_OBJECT *LengthOp; + ACPI_PARSE_OBJECT *DataOp; TotalFolds++; @@ -574,17 +578,22 @@ TrInstallReducedConstant ( Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; Op->Common.AmlOpcode = AML_STRING_OP; - Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1; + Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1; Op->Common.Value.String = ObjDesc->String.Pointer; DbgPrint (ASL_PARSE_OUTPUT, "Constant expression reduced to (STRING) %s\n\n", Op->Common.Value.String); - break; case ACPI_TYPE_BUFFER: - + /* + * Create a new parse subtree of the form: + * + * BUFFER (Buffer AML opcode) + * INTEGER (Buffer length in bytes) + * RAW_DATA (Buffer byte data) + */ Op->Asl.ParseOpcode = PARSEOP_BUFFER; Op->Common.AmlOpcode = AML_BUFFER_OP; Op->Asl.CompileFlags = NODE_AML_PACKAGE; @@ -592,28 +601,24 @@ TrInstallReducedConstant ( /* Child node is the buffer length */ - RootOp = TrAllocateNode (PARSEOP_INTEGER); + LengthOp = TrAllocateNode (PARSEOP_INTEGER); - RootOp->Asl.AmlOpcode = AML_DWORD_OP; - RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length; - RootOp->Asl.Parent = Op; + LengthOp->Asl.AmlOpcode = AML_DWORD_OP; + LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length; + LengthOp->Asl.Parent = Op; + (void) OpcSetOptimalIntegerSize (LengthOp); - (void) OpcSetOptimalIntegerSize (RootOp); - - Op->Asl.Child = RootOp; - Op = RootOp; - UtSetParseOpName (Op); + Op->Asl.Child = LengthOp; - /* Peer to the child is the raw buffer data */ + /* Next child is the raw buffer data */ - RootOp = TrAllocateNode (PARSEOP_RAW_DATA); - RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; - RootOp->Asl.AmlLength = ObjDesc->Buffer.Length; - RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; - RootOp->Asl.Parent = Op->Asl.Parent; + DataOp = TrAllocateNode (PARSEOP_RAW_DATA); + DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; + DataOp->Asl.AmlLength = ObjDesc->Buffer.Length; + DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; + DataOp->Asl.Parent = Op; - Op->Asl.Next = RootOp; - Op = RootOp; + LengthOp->Asl.Next = DataOp; DbgPrint (ASL_PARSE_OUTPUT, "Constant expression reduced to (BUFFER) length %X\n\n", diff --git a/sys/contrib/dev/acpica/compiler/aslglobal.h b/sys/contrib/dev/acpica/compiler/aslglobal.h index c61b8ff..0696b67 100644 --- a/sys/contrib/dev/acpica/compiler/aslglobal.h +++ b/sys/contrib/dev/acpica/compiler/aslglobal.h @@ -73,6 +73,7 @@ ASL_FILE_INFO Gbl_Files [ASL_NUM_FILES] = {NULL, NULL, "Binary Output:", "AML Output"}, {NULL, NULL, "Source Output:", "Source Output"}, {NULL, NULL, "Preprocessor: ", "Preprocessor Output"}, + {NULL, NULL, "Preprocessor: ", "Preprocessor Temp File"}, {NULL, NULL, "Listing File: ", "Listing Output"}, {NULL, NULL, "Hex Dump: ", "Hex Table Output"}, {NULL, NULL, "Namespace: ", "Namespace Output"}, @@ -123,10 +124,10 @@ ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_CurrentLineBuffer, NUL ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_LineBufPtr, NULL); ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_LineBufferSize, ASL_DEFAULT_LINE_BUFFER_SIZE); ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentColumn, 0); -ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_PreviousLineNumber, 0); ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentLineNumber, 1); ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_LogicalLineNumber, 1); ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_CurrentLineOffset, 0); +ASL_EXTERN UINT32 ASL_INIT_GLOBAL (Gbl_OriginalInputFileSize, 0); ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_SyntaxError, 0); /* Exception reporting */ @@ -146,6 +147,7 @@ ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_UseDefaultAmlFilename, ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_MapfileFlag, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NsOutputFlag, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_PreprocessorOutputFlag, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_KeepPreprocessorTempFile, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DebugFlag, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_AsmOutputFlag, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_C_OutputFlag, FALSE); diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c index 99745ad..611183a 100644 --- a/sys/contrib/dev/acpica/compiler/aslmain.c +++ b/sys/contrib/dev/acpica/compiler/aslmain.c @@ -261,7 +261,7 @@ AslSignalHandler ( /* Close all open files */ - Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL; /* the .i file is same as source file */ + Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL; /* the .pre file is same as source file */ for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++) { diff --git a/sys/contrib/dev/acpica/compiler/aslmapenter.c b/sys/contrib/dev/acpica/compiler/aslmapenter.c index 87ad28a..2d2b863 100644 --- a/sys/contrib/dev/acpica/compiler/aslmapenter.c +++ b/sys/contrib/dev/acpica/compiler/aslmapenter.c @@ -239,7 +239,7 @@ MpCreateGpioInfo ( /* Sort on source DeviceName first */ while (NextGpio && - (ACPI_STRCMP (DeviceName, NextGpio->DeviceName) > 0)) + (strcmp (DeviceName, NextGpio->DeviceName) > 0)) { PrevGpio = NextGpio; NextGpio = NextGpio->Next; @@ -249,7 +249,7 @@ MpCreateGpioInfo ( while (NextGpio && (NextGpio->PinNumber < PinNumber) && - !ACPI_STRCMP (DeviceName, NextGpio->DeviceName)) + !strcmp (DeviceName, NextGpio->DeviceName)) { PrevGpio = NextGpio; NextGpio = NextGpio->Next; @@ -316,7 +316,7 @@ MpCreateSerialInfo ( /* Sort on source DeviceName */ while (NextSerial && - (ACPI_STRCMP (DeviceName, NextSerial->DeviceName) > 0)) + (strcmp (DeviceName, NextSerial->DeviceName) > 0)) { PrevSerial = NextSerial; NextSerial = NextSerial->Next; @@ -326,7 +326,7 @@ MpCreateSerialInfo ( while (NextSerial && (NextSerial->Address < Address) && - !ACPI_STRCMP (DeviceName, NextSerial->DeviceName)) + !strcmp (DeviceName, NextSerial->DeviceName)) { PrevSerial = NextSerial; NextSerial = NextSerial->Next; diff --git a/sys/contrib/dev/acpica/compiler/aslmapoutput.c b/sys/contrib/dev/acpica/compiler/aslmapoutput.c index 622b1bd..1cf1e53 100644 --- a/sys/contrib/dev/acpica/compiler/aslmapoutput.c +++ b/sys/contrib/dev/acpica/compiler/aslmapoutput.c @@ -207,7 +207,7 @@ MpEmitGpioInfo ( /* Print header info for the controller itself */ if (!PrevDeviceName || - ACPI_STRCMP (PrevDeviceName, Info->DeviceName)) + strcmp (PrevDeviceName, Info->DeviceName)) { FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\nGPIO Controller: %-8s %-28s", @@ -360,7 +360,7 @@ MpEmitSerialInfo ( /* Print header info for the controller itself */ if (!PrevDeviceName || - ACPI_STRCMP (PrevDeviceName, Info->DeviceName)) + strcmp (PrevDeviceName, Info->DeviceName)) { FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n%s Controller: ", Type); diff --git a/sys/contrib/dev/acpica/compiler/aslmethod.c b/sys/contrib/dev/acpica/compiler/aslmethod.c index fa9216e..bee488f 100644 --- a/sys/contrib/dev/acpica/compiler/aslmethod.c +++ b/sys/contrib/dev/acpica/compiler/aslmethod.c @@ -430,7 +430,7 @@ MtMethodAnalysisWalkBegin ( /* Special typechecking for _HID */ - if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) + if (!strcmp (METHOD_NAME__HID, Op->Asl.NameSeg)) { Next = Op->Asl.Child->Asl.Next; AnCheckId (Next, ASL_TYPE_HID); @@ -438,7 +438,7 @@ MtMethodAnalysisWalkBegin ( /* Special typechecking for _CID */ - else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) + else if (!strcmp (METHOD_NAME__CID, Op->Asl.NameSeg)) { Next = Op->Asl.Child->Asl.Next; diff --git a/sys/contrib/dev/acpica/compiler/aslopcodes.c b/sys/contrib/dev/acpica/compiler/aslopcodes.c index d4dbbe3..43628f9 100644 --- a/sys/contrib/dev/acpica/compiler/aslopcodes.c +++ b/sys/contrib/dev/acpica/compiler/aslopcodes.c @@ -636,7 +636,7 @@ OpcDoEisaId ( * The EISAID string must be exactly 7 characters and of the form * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001") */ - if (ACPI_STRLEN (InString) != 7) + if (strlen (InString) != 7) { Status = AE_BAD_PARAMETER; } @@ -855,7 +855,7 @@ OpcFindName ( for (i = 0, Str = List[0]; Str; i++, Str = List[i]) { - if (!(ACPI_STRNCMP (Str, Name, ACPI_STRLEN (Name)))) + if (!(strncmp (Str, Name, strlen (Name)))) { *Index = i; return (TRUE); @@ -907,7 +907,7 @@ OpcDoPld ( return; } - ACPI_MEMSET (&PldInfo, 0, sizeof (ACPI_PLD_INFO)); + memset (&PldInfo, 0, sizeof (ACPI_PLD_INFO)); Node = Op->Asl.Child; while (Node) diff --git a/sys/contrib/dev/acpica/compiler/asloperands.c b/sys/contrib/dev/acpica/compiler/asloperands.c index b2972d4..df63357 100644 --- a/sys/contrib/dev/acpica/compiler/asloperands.c +++ b/sys/contrib/dev/acpica/compiler/asloperands.c @@ -932,7 +932,7 @@ OpnDoDefinitionBlock ( if (Child->Asl.Value.String) { Gbl_TableSignature = Child->Asl.Value.String; - if (ACPI_STRLEN (Gbl_TableSignature) != 4) + if (strlen (Gbl_TableSignature) != 4) { AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, "Length not exactly 4"); @@ -967,9 +967,9 @@ OpnDoDefinitionBlock ( Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; if (Child->Asl.Value.String) { - Length = ACPI_STRLEN (Child->Asl.Value.String); + Length = strlen (Child->Asl.Value.String); Gbl_TableId = UtStringCacheCalloc (Length + 1); - ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String); + strcpy (Gbl_TableId, Child->Asl.Value.String); /* * Convert anything non-alphanumeric to an underscore. This diff --git a/sys/contrib/dev/acpica/compiler/aslopt.c b/sys/contrib/dev/acpica/compiler/aslopt.c index 1079f9c..a65a25e 100644 --- a/sys/contrib/dev/acpica/compiler/aslopt.c +++ b/sys/contrib/dev/acpica/compiler/aslopt.c @@ -168,9 +168,9 @@ OptSearchToRoot ( /* We must allocate a new string for the name (TargetPath gets deleted) */ *NewPath = UtStringCacheCalloc (ACPI_NAME_SIZE + 1); - ACPI_STRCPY (*NewPath, Path); + strcpy (*NewPath, Path); - if (ACPI_STRNCMP (*NewPath, "_T_", 3)) + if (strncmp (*NewPath, "_T_", 3)) { AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op, *NewPath); @@ -341,7 +341,7 @@ OptBuildShortestPath ( Index = TargetPath->Length; } - ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]); + strcpy (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal)); /* @@ -358,11 +358,11 @@ OptBuildShortestPath ( return (Status); } - if (ACPI_STRLEN (NewPath) >= AmlNameStringLength) + if (strlen (NewPath) >= AmlNameStringLength) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " NOT SHORTER (New %u old %u)", - (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength)); + (UINT32) strlen (NewPath), (UINT32) AmlNameStringLength)); ACPI_FREE (NewPathExternal); return (AE_NOT_FOUND); } @@ -597,7 +597,7 @@ OptOptimizeNamePath ( * The original path must be longer than one NameSeg (4 chars) for there * to be any possibility that it can be optimized to a shorter string */ - AmlNameStringLength = ACPI_STRLEN (AmlNameString); + AmlNameStringLength = strlen (AmlNameString); if (AmlNameStringLength <= ACPI_NAME_SIZE) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, @@ -745,7 +745,7 @@ OptOptimizeNamePath ( */ if (ACPI_SUCCESS (Status)) { - HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath)); + HowMuchShorter = (AmlNameStringLength - strlen (NewPath)); OptTotal += HowMuchShorter; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, @@ -761,12 +761,12 @@ OptOptimizeNamePath ( * (alias name) is the second operand */ Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath; - Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath); + Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath); } else { Op->Asl.Child->Asl.Value.String = NewPath; - Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath); + Op->Asl.Child->Asl.AmlLength = strlen (NewPath); } } else if (Flags & AML_CREATE) @@ -781,14 +781,14 @@ OptOptimizeNamePath ( /* Update the parse node with the new NamePath */ NextOp->Asl.Value.String = NewPath; - NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath); + NextOp->Asl.AmlLength = strlen (NewPath); } else { /* Update the parse node with the new NamePath */ Op->Asl.Value.String = NewPath; - Op->Asl.AmlLength = ACPI_STRLEN (NewPath); + Op->Asl.AmlLength = strlen (NewPath); } } else diff --git a/sys/contrib/dev/acpica/compiler/asloptions.c b/sys/contrib/dev/acpica/compiler/asloptions.c index cc20bcd..4cff853 100644 --- a/sys/contrib/dev/acpica/compiler/asloptions.c +++ b/sys/contrib/dev/acpica/compiler/asloptions.c @@ -194,6 +194,7 @@ AslDoOptions ( DtParserdebug = 1; PrParserdebug = 1; Gbl_DebugFlag = TRUE; + Gbl_KeepPreprocessorTempFile = TRUE; break; case 'p': /* Prune ASL parse tree */ diff --git a/sys/contrib/dev/acpica/compiler/aslprintf.c b/sys/contrib/dev/acpica/compiler/aslprintf.c index c8647ea..1d8d4d7 100644 --- a/sys/contrib/dev/acpica/compiler/aslprintf.c +++ b/sys/contrib/dev/acpica/compiler/aslprintf.c @@ -186,7 +186,7 @@ OpcParsePrintf ( if (StringToProcess) { NewString = UtStringCacheCalloc (StringLength + 1); - ACPI_STRNCPY (NewString, StartPosition, StringLength); + strncpy (NewString, StartPosition, StringLength); NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL); NewOp->Asl.Value.String = NewString; @@ -275,7 +275,7 @@ OpcParsePrintf ( if (StringToProcess) { NewString = UtStringCacheCalloc (StringLength + 1); - ACPI_STRNCPY (NewString, StartPosition, StringLength); + strncpy (NewString, StartPosition, StringLength); NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL); NewOp->Asl.Value.String = NewString; diff --git a/sys/contrib/dev/acpica/compiler/aslstartup.c b/sys/contrib/dev/acpica/compiler/aslstartup.c index 85e2f88..211658b 100644 --- a/sys/contrib/dev/acpica/compiler/aslstartup.c +++ b/sys/contrib/dev/acpica/compiler/aslstartup.c @@ -359,6 +359,8 @@ AslDoOneFile ( return (AE_ERROR); } + Gbl_OriginalInputFileSize = FlGetFileSize (ASL_FILE_INPUT); + /* Determine input file type */ Gbl_FileType = AslDetectSourceFileType (&Gbl_Files[ASL_FILE_INPUT]); diff --git a/sys/contrib/dev/acpica/compiler/aslsupport.l b/sys/contrib/dev/acpica/compiler/aslsupport.l index b3149cf..0016626 100644 --- a/sys/contrib/dev/acpica/compiler/aslsupport.l +++ b/sys/contrib/dev/acpica/compiler/aslsupport.l @@ -113,6 +113,7 @@ AslDoLineDirective ( char *Filename; UINT32 i; + Gbl_HasIncludeFiles = TRUE; /* Eat the entire line that contains the #line directive */ @@ -713,7 +714,7 @@ DoCharacter: * string and resume processing of the next character */ ConvertBuffer[i] = 0; - Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8); + Digit = (UINT8) strtoul (ConvertBuffer, NULL, 8); /* Check for NULL or non-ascii character (ignore if so) */ @@ -749,7 +750,7 @@ DoCharacter: /* Up to two hex digits allowed */ - if (!ACPI_IS_XDIGIT (StringChar) || + if (!isxdigit (StringChar) || (i > 1)) { /* @@ -757,7 +758,7 @@ DoCharacter: * string and resume processing of the next character */ ConvertBuffer[i] = 0; - Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16); + Digit = (UINT8) strtoul (ConvertBuffer, NULL, 16); /* Check for NULL or non-ascii character (ignore if so) */ @@ -830,7 +831,7 @@ CompletedString: return (FALSE); } - ACPI_STRCPY (CleanString, MsgBuffer); + strcpy (CleanString, MsgBuffer); AslCompilerlval.s = CleanString; return (TRUE); diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h index 4bd24da..343c364 100644 --- a/sys/contrib/dev/acpica/compiler/asltypes.h +++ b/sys/contrib/dev/acpica/compiler/asltypes.h @@ -148,32 +148,56 @@ typedef struct asl_file_status /* * File types. Note: Any changes to this table must also be reflected * in the Gbl_Files array. + * + * Corresponding filename suffixes are in comments + * + * NOTE: Don't move the first 4 file types */ typedef enum { ASL_FILE_STDOUT = 0, ASL_FILE_STDERR, - ASL_FILE_INPUT, - ASL_FILE_AML_OUTPUT, /* Don't move these first 4 file types */ - ASL_FILE_SOURCE_OUTPUT, - ASL_FILE_PREPROCESSOR, - ASL_FILE_LISTING_OUTPUT, - ASL_FILE_HEX_OUTPUT, - ASL_FILE_NAMESPACE_OUTPUT, - ASL_FILE_DEBUG_OUTPUT, - ASL_FILE_ASM_SOURCE_OUTPUT, - ASL_FILE_C_SOURCE_OUTPUT, - ASL_FILE_ASM_INCLUDE_OUTPUT, - ASL_FILE_C_INCLUDE_OUTPUT, - ASL_FILE_C_OFFSET_OUTPUT, - ASL_FILE_MAP_OUTPUT + ASL_FILE_INPUT, /* .asl */ + ASL_FILE_AML_OUTPUT, /* .aml */ + ASL_FILE_SOURCE_OUTPUT, /* .src */ + ASL_FILE_PREPROCESSOR, /* .pre */ + ASL_FILE_PREPROCESSOR_USER, /* .i */ + ASL_FILE_LISTING_OUTPUT, /* .lst */ + ASL_FILE_HEX_OUTPUT, /* .hex */ + ASL_FILE_NAMESPACE_OUTPUT, /* .nsp */ + ASL_FILE_DEBUG_OUTPUT, /* .txt */ + ASL_FILE_ASM_SOURCE_OUTPUT, /* .asm */ + ASL_FILE_C_SOURCE_OUTPUT, /* .c */ + ASL_FILE_ASM_INCLUDE_OUTPUT,/* .inc */ + ASL_FILE_C_INCLUDE_OUTPUT, /* .h */ + ASL_FILE_C_OFFSET_OUTPUT, /* offset.h */ + ASL_FILE_MAP_OUTPUT /* .map */ } ASL_FILE_TYPES; -#define ASL_MAX_FILE_TYPE 15 +#define ASL_MAX_FILE_TYPE 16 #define ASL_NUM_FILES (ASL_MAX_FILE_TYPE + 1) +/* filename suffixes for output files */ + +#define FILE_SUFFIX_PREPROC_USER "i " +#define FILE_SUFFIX_PREPROCESSOR "pre" +#define FILE_SUFFIX_AML_CODE "aml" +#define FILE_SUFFIX_MAP "map" +#define FILE_SUFFIX_LISTING "lst" +#define FILE_SUFFIX_HEX_DUMP "hex" +#define FILE_SUFFIX_DEBUG "txt" +#define FILE_SUFFIX_SOURCE "src" +#define FILE_SUFFIX_NAMESPACE "nsp" +#define FILE_SUFFIX_ASM_SOURCE "asm" +#define FILE_SUFFIX_C_SOURCE "c" +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define FILE_SUFFIX_ASM_INCLUDE "inc" +#define FILE_SUFFIX_C_INCLUDE "h" +#define FILE_SUFFIX_ASL_CODE "asl" +#define FILE_SUFFIX_C_OFFSET "offset.h" + /* Cache block structure for ParseOps and Strings */ diff --git a/sys/contrib/dev/acpica/compiler/aslutils.c b/sys/contrib/dev/acpica/compiler/aslutils.c index dadd6b1..e0511a4 100644 --- a/sys/contrib/dev/acpica/compiler/aslutils.c +++ b/sys/contrib/dev/acpica/compiler/aslutils.c @@ -441,17 +441,20 @@ UtDisplaySummary ( "%-14s %s - %u lines, %u bytes, %u keywords\n", "ASL Input:", Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, - Gbl_InputByteCount, TotalKeywords); + Gbl_OriginalInputFileSize, TotalKeywords); /* AML summary */ if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) { - FlPrintFile (FileId, - "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n", - "AML Output:", - Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength, - TotalNamedObjects, TotalExecutableOpcodes); + if (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle) + { + FlPrintFile (FileId, + "%-14s %s - %u bytes, %u named objects, %u executable opcodes\n", + "AML Output:", + Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength, + TotalNamedObjects, TotalExecutableOpcodes); + } } } @@ -471,9 +474,9 @@ UtDisplaySummary ( continue; } - /* .I is a temp file unless specifically requested */ + /* .PRE is the preprocessor intermediate file */ - if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_PreprocessorOutputFlag)) + if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_KeepPreprocessorTempFile)) { continue; } @@ -932,7 +935,7 @@ UtDoConstant ( char ErrBuf[64]; - Status = UtStrtoul64 (String, 0, &Converted); + Status = stroul64 (String, 0, &Converted); if (ACPI_FAILURE (Status)) { sprintf (ErrBuf, "%s %s\n", "Conversion error:", @@ -948,7 +951,7 @@ UtDoConstant ( /******************************************************************************* * - * FUNCTION: UtStrtoul64 + * FUNCTION: stroul64 * * PARAMETERS: String - Null terminated string * Terminater - Where a pointer to the terminating byte @@ -962,7 +965,7 @@ UtDoConstant ( ******************************************************************************/ ACPI_STATUS -UtStrtoul64 ( +stroul64 ( char *String, UINT32 Base, UINT64 *RetInteger) diff --git a/sys/contrib/dev/acpica/compiler/asluuid.c b/sys/contrib/dev/acpica/compiler/asluuid.c index 4e345e9..850ac6a 100644 --- a/sys/contrib/dev/acpica/compiler/asluuid.c +++ b/sys/contrib/dev/acpica/compiler/asluuid.c @@ -69,7 +69,7 @@ AuValidateUuid ( UINT32 i; - if (!InString || (ACPI_STRLEN (InString) != UUID_STRING_LENGTH)) + if (!InString || (strlen (InString) != UUID_STRING_LENGTH)) { return (AE_BAD_PARAMETER); } diff --git a/sys/contrib/dev/acpica/compiler/dtcompile.c b/sys/contrib/dev/acpica/compiler/dtcompile.c index 20da143..506c4cd 100644 --- a/sys/contrib/dev/acpica/compiler/dtcompile.c +++ b/sys/contrib/dev/acpica/compiler/dtcompile.c @@ -302,7 +302,7 @@ DtCompileDataTable ( return (AE_ERROR); } - Gbl_Signature = UtStringCacheCalloc (ACPI_STRLEN (Signature) + 1); + Gbl_Signature = UtStringCacheCalloc (strlen (Signature) + 1); strcpy (Gbl_Signature, Signature); /* @@ -358,6 +358,8 @@ DtCompileDataTable ( TableData = AcpiDmGetTableData (Signature); if (!TableData || Gbl_CompileGeneric) { + /* Unknown table signature and/or force generic compile */ + DtCompileGeneric ((void **) FieldList, NULL, NULL); goto FinishHeader; } @@ -454,7 +456,7 @@ DtCompileTable ( /* Ignore optional subtable if name does not match */ if ((Info->Flags & DT_OPTIONAL) && - ACPI_STRCMP ((*Field)->Name, Info->Name)) + strcmp ((*Field)->Name, Info->Name)) { *RetSubtable = NULL; return (AE_OK); @@ -591,7 +593,7 @@ DtCompileTable ( DtSetSubtableLength (InlineSubtable); - ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength); + memcpy (Buffer, InlineSubtable->Buffer, FieldLength); LocalField = *Field; break; diff --git a/sys/contrib/dev/acpica/compiler/dtcompiler.h b/sys/contrib/dev/acpica/compiler/dtcompiler.h index 201b2db..daff7aa 100644 --- a/sys/contrib/dev/acpica/compiler/dtcompiler.h +++ b/sys/contrib/dev/acpica/compiler/dtcompiler.h @@ -181,7 +181,13 @@ DtCompilePadding ( UINT32 DtGetNextLine ( - FILE *Handle); + FILE *Handle, + UINT32 Flags); + +/* Flags for DtGetNextLine */ + +#define DT_ALLOW_MULTILINE_QUOTES 0x01 + DT_FIELD * DtScanFile ( diff --git a/sys/contrib/dev/acpica/compiler/dtexpress.c b/sys/contrib/dev/acpica/compiler/dtexpress.c index 90054c9..4316b79 100644 --- a/sys/contrib/dev/acpica/compiler/dtexpress.c +++ b/sys/contrib/dev/acpica/compiler/dtexpress.c @@ -413,7 +413,7 @@ DtLookupLabel ( LabelField = Gbl_LabelList; while (LabelField) { - if (!ACPI_STRCMP (Name, LabelField->Value)) + if (!strcmp (Name, LabelField->Value)) { return (LabelField); } diff --git a/sys/contrib/dev/acpica/compiler/dtfield.c b/sys/contrib/dev/acpica/compiler/dtfield.c index 3b191ab..621636c 100644 --- a/sys/contrib/dev/acpica/compiler/dtfield.c +++ b/sys/contrib/dev/acpica/compiler/dtfield.c @@ -166,7 +166,7 @@ DtCompileString ( UINT32 Length; - Length = ACPI_STRLEN (Field->Value); + Length = strlen (Field->Value); /* Check if the string is too long for the field */ @@ -177,7 +177,7 @@ DtCompileString ( Length = ByteLength; } - ACPI_MEMCPY (Buffer, Field->Value, Length); + memcpy (Buffer, Field->Value, Length); } @@ -212,7 +212,7 @@ DtCompileUnicode ( AsciiString = Field->Value; UnicodeString = (UINT16 *) Buffer; - Count = ACPI_STRLEN (AsciiString) + 1; + Count = strlen (AsciiString) + 1; /* Convert to Unicode string (including null terminator) */ @@ -318,7 +318,7 @@ DtCompileInteger ( /* TBD: Should use a flag rather than compare "Reserved" */ - if (!ACPI_STRCMP (Field->Name, "Reserved")) + if (!strcmp (Field->Name, "Reserved")) { if (Flags & DT_NON_ZERO) { @@ -359,7 +359,7 @@ DtCompileInteger ( DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer); } - ACPI_MEMCPY (Buffer, &Value, ByteLength); + memcpy (Buffer, &Value, ByteLength); return; } @@ -391,7 +391,7 @@ DtNormalizeBuffer ( char c; - NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1); + NewBuffer = UtLocalCalloc (strlen (Buffer) + 1); TmpBuffer = NewBuffer; while ((c = *Buffer++)) diff --git a/sys/contrib/dev/acpica/compiler/dtio.c b/sys/contrib/dev/acpica/compiler/dtio.c index 4b05bd0..fed9925 100644 --- a/sys/contrib/dev/acpica/compiler/dtio.c +++ b/sys/contrib/dev/acpica/compiler/dtio.c @@ -129,7 +129,7 @@ DtTrim ( /* Skip lines that start with a space */ - if (!ACPI_STRCMP (String, " ")) + if (!strcmp (String, " ")) { ReturnString = UtStringCacheCalloc (1); return (ReturnString); @@ -138,7 +138,7 @@ DtTrim ( /* Setup pointers to start and end of input string */ Start = String; - End = String + ACPI_STRLEN (String) - 1; + End = String + strlen (String) - 1; /* Find first non-whitespace character */ @@ -180,9 +180,9 @@ DtTrim ( Length = ACPI_PTR_DIFF (End, Start) + 1; ReturnString = UtStringCacheCalloc (Length + 1); - if (ACPI_STRLEN (Start)) + if (strlen (Start)) { - ACPI_STRNCPY (ReturnString, Start, Length); + strncpy (ReturnString, Start, Length); } ReturnString[Length] = 0; @@ -313,7 +313,7 @@ DtParseLine ( Length = ACPI_PTR_DIFF (End, Start); TmpName = UtLocalCalloc (Length + 1); - ACPI_STRNCPY (TmpName, Start, Length); + strncpy (TmpName, Start, Length); Name = DtTrim (TmpName); ACPI_FREE (TmpName); @@ -360,7 +360,7 @@ DtParseLine ( Length = ACPI_PTR_DIFF (End, Start); TmpValue = UtLocalCalloc (Length + 1); - ACPI_STRNCPY (TmpValue, Start, Length); + strncpy (TmpValue, Start, Length); Value = DtTrim (TmpValue); ACPI_FREE (TmpValue); @@ -406,7 +406,8 @@ DtParseLine ( UINT32 DtGetNextLine ( - FILE *Handle) + FILE *Handle, + UINT32 Flags) { BOOLEAN LineNotAllBlanks = FALSE; UINT32 State = DT_NORMAL_TEXT; @@ -415,7 +416,7 @@ DtGetNextLine ( int c; - ACPI_MEMSET (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); + memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); for (i = 0; ;) { /* @@ -550,9 +551,12 @@ DtGetNextLine ( case '\n': - AcpiOsPrintf ("ERROR at line %u: Unterminated quoted string\n", - Gbl_CurrentLineNumber++); - State = DT_NORMAL_TEXT; + if (!(Flags & DT_ALLOW_MULTILINE_QUOTES)) + { + AcpiOsPrintf ("ERROR at line %u: Unterminated quoted string\n", + Gbl_CurrentLineNumber++); + State = DT_NORMAL_TEXT; + } break; default: /* Get next character */ @@ -746,7 +750,7 @@ DtScanFile ( /* Scan line-by-line */ - while ((Offset = DtGetNextLine (Handle)) != ASL_EOF) + while ((Offset = DtGetNextLine (Handle, 0)) != ASL_EOF) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s", Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer)); @@ -897,7 +901,7 @@ DtDumpBuffer ( } BufChar = Buffer[(ACPI_SIZE) i + j]; - if (ACPI_IS_PRINT (BufChar)) + if (isprint (BufChar)) { FlPrintFile (FileId, "%c", BufChar); } diff --git a/sys/contrib/dev/acpica/compiler/dtparser.y b/sys/contrib/dev/acpica/compiler/dtparser.y index 0271d78..9d6f1e2 100644 --- a/sys/contrib/dev/acpica/compiler/dtparser.y +++ b/sys/contrib/dev/acpica/compiler/dtparser.y @@ -48,6 +48,13 @@ #define _COMPONENT DT_COMPILER ACPI_MODULE_NAME ("dtparser") +void * AslLocalAllocate (unsigned int Size); + +/* Bison/yacc configuration */ + +#undef alloca +#define alloca AslLocalAllocate + int DtParserlex (void); int DtParserparse (void); void DtParsererror (char const *msg); @@ -162,15 +169,15 @@ Expression /* Default base for a non-prefixed integer is 16 */ - | EXPOP_NUMBER { UtStrtoul64 (DtParsertext, 16, &$$);} + | EXPOP_NUMBER { stroul64 (DtParsertext, 16, &$$);} /* Standard hex number (0x1234) */ - | EXPOP_HEX_NUMBER { UtStrtoul64 (DtParsertext, 16, &$$);} + | EXPOP_HEX_NUMBER { stroul64 (DtParsertext, 16, &$$);} - /* TBD: Decimal number with prefix (0d1234) - Not supported by UtStrtoul64 at this time */ + /* TBD: Decimal number with prefix (0d1234) - Not supported by stroul64 at this time */ - | EXPOP_DECIMAL_NUMBER { UtStrtoul64 (DtParsertext, 10, &$$);} + | EXPOP_DECIMAL_NUMBER { stroul64 (DtParsertext, 10, &$$);} ; %% diff --git a/sys/contrib/dev/acpica/compiler/dtsubtable.c b/sys/contrib/dev/acpica/compiler/dtsubtable.c index 1152656..8cb5253 100644 --- a/sys/contrib/dev/acpica/compiler/dtsubtable.c +++ b/sys/contrib/dev/acpica/compiler/dtsubtable.c @@ -80,7 +80,7 @@ DtCreateSubtable ( String = UtStringCacheCalloc (Length); Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); - ACPI_MEMCPY (Subtable->Buffer, Buffer, Length); + memcpy (Subtable->Buffer, Buffer, Length); Subtable->Length = Length; Subtable->TotalLength = Length; @@ -379,6 +379,6 @@ DtSetSubtableLength ( return; } - ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength, + memcpy (Subtable->LengthField, &Subtable->TotalLength, Subtable->SizeOfLengthField); } diff --git a/sys/contrib/dev/acpica/compiler/dttable.c b/sys/contrib/dev/acpica/compiler/dttable.c index bae80ad..1c32fe0 100644 --- a/sys/contrib/dev/acpica/compiler/dttable.c +++ b/sys/contrib/dev/acpica/compiler/dttable.c @@ -1824,7 +1824,7 @@ DtCompileIvrs ( if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE) { while (*PFieldList && - !ACPI_STRCMP ((*PFieldList)->Name, "Entry Type")) + !strcmp ((*PFieldList)->Name, "Entry Type")) { SubtableStart = *PFieldList; DtCompileInteger (&EntryType, *PFieldList, 1, 0); @@ -3403,13 +3403,13 @@ DtCompileGeneric ( /* Now we can actually compile the parse tree */ - if (*Length) + if (Length && *Length) { *Length = 0; } while (*PFieldList) { - if (Name && !ACPI_STRCMP ((*PFieldList)->Name, Name)) + if (Name && !strcmp ((*PFieldList)->Name, Name)) { break; } diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.c b/sys/contrib/dev/acpica/compiler/dttemplate.c index 90b6b17..07e930f 100644 --- a/sys/contrib/dev/acpica/compiler/dttemplate.c +++ b/sys/contrib/dev/acpica/compiler/dttemplate.c @@ -85,6 +85,7 @@ AcpiUtIsSpecialTable ( { if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (Signature, ACPI_SIG_OSDT) || ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) || ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS) || ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME)) @@ -127,8 +128,8 @@ DtCreateTemplates ( } AcpiUtStrupr (Signature); - if (!ACPI_STRCMP (Signature, "ALL") || - !ACPI_STRCMP (Signature, "*")) + if (!strcmp (Signature, "ALL") || + !strcmp (Signature, "*")) { /* Create all available/known templates */ @@ -327,7 +328,7 @@ DtCreateOneTemplate ( AcpiOsPrintf ("/*\n"); AcpiOsPrintf (ACPI_COMMON_HEADER ("iASL Compiler/Disassembler", " * ")); - AcpiOsPrintf (" * Template for [%4.4s] ACPI Table\n", + AcpiOsPrintf (" * Template for [%4.4s] ACPI Table", Signature); /* Dump the actual ACPI table */ @@ -336,6 +337,8 @@ DtCreateOneTemplate ( { /* Normal case, tables that appear in AcpiDmTableData */ + AcpiOsPrintf (" (static data table)\n"); + if (Gbl_VerboseTemplates) { AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]" @@ -344,7 +347,7 @@ DtCreateOneTemplate ( else { AcpiOsPrintf (" * Format: [ByteLength]" - " FieldName : HexFieldValue\n */\n\n"); + " FieldName : HexFieldValue\n */\n"); } AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER, @@ -352,9 +355,11 @@ DtCreateOneTemplate ( } else { - /* Special ACPI tables - DSDT, SSDT, FADT, RSDP */ + /* Special ACPI tables - DSDT, SSDT, OSDT, FADT, RSDP */ + + AcpiOsPrintf (" (AML byte code table)\n"); - AcpiOsPrintf (" */\n\n"); + AcpiOsPrintf (" */\n"); if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) { Actual = fwrite (TemplateDsdt, 1, sizeof (TemplateDsdt) -1, File); @@ -377,6 +382,17 @@ DtCreateOneTemplate ( goto Cleanup; } } + else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_OSDT)) + { + Actual = fwrite (TemplateOsdt, 1, sizeof (TemplateOsdt) -1, File); + if (Actual != sizeof (TemplateOsdt) -1) + { + fprintf (stderr, + "Could not write to output file %s\n", DisasmFilename); + Status = AE_ERROR; + goto Cleanup; + } + } else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) /* FADT */ { AcpiDmDumpDataTable (ACPI_CAST_PTR (ACPI_TABLE_HEADER, diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.h b/sys/contrib/dev/acpica/compiler/dttemplate.h index 1b27b4e..6d76f4d 100644 --- a/sys/contrib/dev/acpica/compiler/dttemplate.h +++ b/sys/contrib/dev/acpica/compiler/dttemplate.h @@ -45,7 +45,7 @@ #define __DTTEMPLATE_H -/* Special templates for DSDT and SSDT (AML byte-code tables) */ +/* Special templates for the ASL/AML tables: DSDT, SSDT, and OSDT */ const char TemplateDsdt[] = "DefinitionBlock (\"dsdt.aml\", \"DSDT\", 2, \"Intel\", \"Template\", 0x00000001)\n" @@ -65,6 +65,15 @@ const char TemplateSsdt[] = " }\n" "}\n\n"; +const char TemplateOsdt[] = + "DefinitionBlock (\"osdt.aml\", \"OSDT\", 2, \"Intel\", \"Template\", 0x00000001)\n" + "{\n" + " Method (MAIN, 0, NotSerialized)\n" + " {\n" + " Return (Zero)\n" + " }\n" + "}\n\n"; + /* Templates for ACPI data tables */ diff --git a/sys/contrib/dev/acpica/compiler/dtutils.c b/sys/contrib/dev/acpica/compiler/dtutils.c index 2d5b762..ce996c4 100644 --- a/sys/contrib/dev/acpica/compiler/dtutils.c +++ b/sys/contrib/dev/acpica/compiler/dtutils.c @@ -241,7 +241,7 @@ DtStrtoul64 ( while (*ThisChar) { - if (ACPI_IS_DIGIT (*ThisChar)) + if (isdigit ((int) *ThisChar)) { /* Convert ASCII 0-9 to Decimal value */ @@ -249,8 +249,8 @@ DtStrtoul64 ( } else /* Letter */ { - ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar); - if (!ACPI_IS_XDIGIT ((char) ThisDigit)) + ThisDigit = (UINT32) toupper ((int) *ThisChar); + if (!isxdigit ((int) ThisDigit)) { /* Not A-F */ @@ -568,7 +568,7 @@ DtGetFieldLength ( Value = DtGetFieldValue (Field); if (Value) { - ByteLength = ACPI_STRLEN (Value) + 1; + ByteLength = strlen (Value) + 1; } else { /* At this point, this is a fatal error */ @@ -633,7 +633,7 @@ DtGetFieldLength ( /* TBD: error if Value is NULL? (as below?) */ - ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16); + ByteLength = (strlen (Value) + 1) * sizeof(UINT16); break; default: diff --git a/sys/contrib/dev/acpica/compiler/prparser.y b/sys/contrib/dev/acpica/compiler/prparser.y index 20d6e6a..f0c5f9b 100644 --- a/sys/contrib/dev/acpica/compiler/prparser.y +++ b/sys/contrib/dev/acpica/compiler/prparser.y @@ -48,6 +48,13 @@ #define _COMPONENT ASL_PREPROCESSOR ACPI_MODULE_NAME ("prparser") +void * AslLocalAllocate (unsigned int Size); + +/* Bison/yacc configuration */ + +#undef alloca +#define alloca AslLocalAllocate + int PrParserlex (void); int PrParserparse (void); void PrParsererror (char const *msg); @@ -175,11 +182,11 @@ Expression /* Default base for a non-prefixed integer is 10 */ - | EXPOP_NUMBER { UtStrtoul64 (PrParsertext, 10, &$$);} + | EXPOP_NUMBER { stroul64 (PrParsertext, 10, &$$);} /* Standard hex number (0x1234) */ - | EXPOP_HEX_NUMBER { UtStrtoul64 (PrParsertext, 16, &$$);} + | EXPOP_HEX_NUMBER { stroul64 (PrParsertext, 16, &$$);} ; %% diff --git a/sys/contrib/dev/acpica/compiler/prscan.c b/sys/contrib/dev/acpica/compiler/prscan.c index 12d303c..cbf82a9 100644 --- a/sys/contrib/dev/acpica/compiler/prscan.c +++ b/sys/contrib/dev/acpica/compiler/prscan.c @@ -67,6 +67,14 @@ PrDoDirective ( char *DirectiveToken, char **Next); +static void +PrGetNextLineInit ( + void); + +static UINT32 +PrGetNextLine ( + FILE *Handle); + static int PrMatchDirective ( char *Directive); @@ -186,7 +194,7 @@ PrInitializeGlobals ( /* Init globals */ Gbl_InputFileList = NULL; - Gbl_CurrentLineNumber = 0; + Gbl_CurrentLineNumber = 1; Gbl_PreprocessorLineNumber = 1; Gbl_PreprocessorError = FALSE; @@ -271,7 +279,7 @@ PrDoPreprocess ( } while (MoreInputFiles); - /* Point compiler input to the new preprocessor output file (.i) */ + /* Point compiler input to the new preprocessor output file (.pre) */ FlCloseFile (ASL_FILE_INPUT); Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; @@ -280,7 +288,10 @@ PrDoPreprocess ( /* Reset globals to allow compiler to run */ FlSeekFile (ASL_FILE_INPUT, 0); - Gbl_CurrentLineNumber = 1; + if (!Gbl_PreprocessOnly) + { + Gbl_CurrentLineNumber = 0; + } DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); } @@ -297,7 +308,8 @@ PrDoPreprocess ( * DESCRIPTION: Preprocess one entire file, line-by-line. * * Input: Raw user ASL from ASL_FILE_INPUT - * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR + * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and + * (optionally) ASL_FILE_PREPROCESSOR_USER * ******************************************************************************/ @@ -305,7 +317,7 @@ static void PrPreprocessInputFile ( void) { - UINT32 Offset; + UINT32 Status; char *Token; char *ReplaceString; PR_DEFINE_INFO *DefineInfo; @@ -314,10 +326,21 @@ PrPreprocessInputFile ( int OffsetAdjust; + PrGetNextLineInit (); + /* Scan line-by-line. Comments and blank lines are skipped by this function */ - while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) + while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) { + Gbl_CurrentLineNumber++; + Gbl_LogicalLineNumber++; + + if ((Status == ASL_WITHIN_COMMENT) || + (Status == ASL_BLANK_LINE)) + { + goto WriteEntireLine; + } + /* Need a copy of the input line for strok() */ strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); @@ -397,24 +420,13 @@ PrPreprocessInputFile ( Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); } - /* - * Emit a #line directive if necessary, to keep the line numbers in - * the (.i) file synchronized with the original source code file, so - * that the correct line number appears in any error messages - * generated by the actual compiler. - */ - if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1)) - { - FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n", - Gbl_CurrentLineNumber); - } - - Gbl_PreviousLineNumber = Gbl_CurrentLineNumber; Gbl_PreprocessorLineNumber++; + +WriteEntireLine: /* * Now we can write the possibly modified source line to the - * preprocessor (.i) file + * preprocessor file(s). */ FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, strlen (Gbl_CurrentLineBuffer)); @@ -654,7 +666,7 @@ PrDoDirective ( { #ifndef MACROS_SUPPORTED AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n", - Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber); + Gbl_CurrentLineBuffer, Gbl_LogicalLineNumber); exit(1); #else PrAddMacro (Token, Next); @@ -691,7 +703,7 @@ PrDoDirective ( #endif DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID "New #define: %s->%s\n", - Gbl_CurrentLineNumber, Token, Token2); + Gbl_LogicalLineNumber, Token, Token2); PrAddDefine (Token, Token2, FALSE); } @@ -760,10 +772,7 @@ PrDoDirective ( "User #line invocation %s\n", Gbl_CurrentLineNumber, Token); - /* Update local line numbers */ - Gbl_CurrentLineNumber = (UINT32) Value; - Gbl_PreviousLineNumber = 0; /* Emit #line into the preprocessor file */ @@ -839,6 +848,107 @@ SyntaxError: /******************************************************************************* * + * FUNCTION: PrGetNextLine, PrGetNextLineInit + * + * PARAMETERS: Handle - Open file handle for the source file + * + * RETURN: Status of the GetLine operation: + * AE_OK - Normal line, OK status + * ASL_WITHIN_COMMENT - Line is part of a multi-line comment + * ASL_EOF - End-of-file reached + * + * DESCRIPTION: Get the next text line from the input file. Does not strip + * comments. + * + ******************************************************************************/ + +#define PR_NORMAL_TEXT 0 +#define PR_WITHIN_COMMENT 1 + +static UINT8 AcpiGbl_LineScanState = PR_NORMAL_TEXT; + +static void +PrGetNextLineInit ( + void) +{ + AcpiGbl_LineScanState = 0; +} + +static UINT32 +PrGetNextLine ( + FILE *Handle) +{ + UINT32 i; + int c = 0; + int PreviousChar; + + + /* Always clear the global line buffer */ + + memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); + for (i = 0; ;) + { + /* + * If line is too long, expand the line buffers. Also increases + * Gbl_LineBufferSize. + */ + if (i >= Gbl_LineBufferSize) + { + UtExpandLineBuffers (); + } + + PreviousChar = c; + c = getc (Handle); + if (c == EOF) + { + return (ASL_EOF); + } + + /* We need to worry about multi-line slash-asterisk comments */ + + /* Check for comment open */ + + if ((AcpiGbl_LineScanState == PR_NORMAL_TEXT) && + (PreviousChar == '/') && (c == '*')) + { + AcpiGbl_LineScanState = PR_WITHIN_COMMENT; + } + + /* Check for comment close */ + + if ((AcpiGbl_LineScanState == PR_WITHIN_COMMENT) && + (PreviousChar == '*') && (c == '/')) + { + AcpiGbl_LineScanState = PR_NORMAL_TEXT; + } + + /* Always copy the character into line buffer */ + + Gbl_CurrentLineBuffer[i] = (char) c; + i++; + + /* Always exit on end-of-line */ + + if (c == '\n') + { + /* Handle multi-line comments */ + + if (AcpiGbl_LineScanState == PR_WITHIN_COMMENT) + { + return (ASL_WITHIN_COMMENT); + } + if (i == 1) + { + return (ASL_BLANK_LINE); + } + return (AE_OK); + } + } +} + + +/******************************************************************************* + * * FUNCTION: PrMatchDirective * * PARAMETERS: Directive - Pointer to directive name token diff --git a/sys/contrib/dev/acpica/compiler/prutils.c b/sys/contrib/dev/acpica/compiler/prutils.c index 7e880b1..751d1a0 100644 --- a/sys/contrib/dev/acpica/compiler/prutils.c +++ b/sys/contrib/dev/acpica/compiler/prutils.c @@ -382,6 +382,8 @@ PrPushInputFileStack ( PR_FILE_NODE *Fnode; + Gbl_HasIncludeFiles = TRUE; + /* Save the current state in an Fnode */ Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE)); @@ -406,11 +408,11 @@ PrPushInputFileStack ( strcpy (Gbl_Files[ASL_FILE_INPUT].Filename, Filename); Gbl_Files[ASL_FILE_INPUT].Handle = InputFile; - Gbl_PreviousLineNumber = 0; - Gbl_CurrentLineNumber = 0; + Gbl_CurrentLineNumber = 1; /* Emit a new #line directive for the include file */ + Gbl_CurrentLineNumber = 1; FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename); } @@ -460,12 +462,11 @@ PrPopInputFileStack ( Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename; Gbl_Files[ASL_FILE_INPUT].Handle = Fnode->File; Gbl_CurrentLineNumber = Fnode->CurrentLineNumber; - Gbl_PreviousLineNumber = 0; /* Emit a new #line directive after the include file */ FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", - Gbl_CurrentLineNumber + 1, Fnode->Filename); + Gbl_CurrentLineNumber, Fnode->Filename); /* All done with this node */ diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c index c11451d..0f236d2 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c +++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c @@ -111,7 +111,7 @@ AcpiDbConvertToNode ( { /* Numeric argument, convert */ - Address = ACPI_STRTOUL (InString, NULL, 16); + Address = strtoul (InString, NULL, 16); Node = ACPI_TO_POINTER (Address); if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) { @@ -189,7 +189,7 @@ AcpiDbSleep ( /* Convert argument to binary and invoke the sleep state */ - SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0); + SleepState = (UINT8) strtoul (ObjectArg, NULL, 0); AcpiDbDoOneSleepState (SleepState); return_ACPI_STATUS (AE_OK); } @@ -561,7 +561,7 @@ AcpiDbDisplayInterfaces ( /* Install - install an interface */ - SubString = ACPI_STRSTR ("INSTALL", ActionArg); + SubString = strstr ("INSTALL", ActionArg); if (SubString) { Status = AcpiInstallInterface (InterfaceNameArg); @@ -575,7 +575,7 @@ AcpiDbDisplayInterfaces ( /* Remove - remove an interface */ - SubString = ACPI_STRSTR ("REMOVE", ActionArg); + SubString = strstr ("REMOVE", ActionArg); if (SubString) { Status = AcpiRemoveInterface (InterfaceNameArg); @@ -736,7 +736,7 @@ AcpiDmCompareAmlResources ( /* Check for descriptor byte match */ - else if (ACPI_MEMCMP (Aml1, Aml2, Aml1Length)) + else if (memcmp (Aml1, Aml2, Aml1Length)) { AcpiOsPrintf ( "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n", @@ -1138,7 +1138,7 @@ AcpiDbDisplayResources ( /* Asterisk means "display resources for all devices" */ - if (!ObjectArg || (!ACPI_STRCMP (ObjectArg, "*"))) + if (!ObjectArg || (!strcmp (ObjectArg, "*"))) { (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL); @@ -1191,7 +1191,7 @@ AcpiDbGenerateGpe ( ACPI_GPE_EVENT_INFO *GpeEventInfo; - GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0); + GpeNumber = strtoul (GpeArg, NULL, 0); /* * If no block arg, or block arg == 0 or 1, use the FADT-defined @@ -1199,7 +1199,7 @@ AcpiDbGenerateGpe ( */ if (BlockArg) { - BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0); + BlockNumber = strtoul (BlockArg, NULL, 0); if (BlockNumber == 1) { BlockNumber = 0; diff --git a/sys/contrib/dev/acpica/components/debugger/dbconvert.c b/sys/contrib/dev/acpica/components/debugger/dbconvert.c index f6c0286..08931e4 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbconvert.c +++ b/sys/contrib/dev/acpica/components/debugger/dbconvert.c @@ -77,7 +77,7 @@ AcpiDbHexCharToValue ( /* Digit must be ascii [0-9a-fA-F] */ - if (!ACPI_IS_XDIGIT (HexChar)) + if (!isxdigit (HexChar)) { return (AE_BAD_HEX_CONSTANT); } @@ -88,7 +88,7 @@ AcpiDbHexCharToValue ( } else { - Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37); + Value = (UINT8) (toupper (HexChar) - 0x37); } *ReturnValue = Value; @@ -306,7 +306,7 @@ AcpiDbConvertToObject ( Object->Type = ACPI_TYPE_STRING; Object->String.Pointer = String; - Object->String.Length = (UINT32) ACPI_STRLEN (String); + Object->String.Length = (UINT32) strlen (String); break; case ACPI_TYPE_BUFFER: @@ -471,7 +471,7 @@ AcpiDbDumpPldBuffer ( /* The two bit-packed buffers should match */ - if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer, + if (memcmp (NewBuffer, BufferDesc->Buffer.Pointer, BufferDesc->Buffer.Length)) { AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n"); diff --git a/sys/contrib/dev/acpica/components/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c index 507c2b0..d71d21d 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbdisply.c +++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c @@ -141,7 +141,7 @@ AcpiDbGetPointer ( ACPI_SIZE Address; - Address = ACPI_STRTOUL (Target, NULL, 16); + Address = strtoul (Target, NULL, 16); ObjPtr = ACPI_TO_POINTER (Address); return (ObjPtr); } diff --git a/sys/contrib/dev/acpica/components/debugger/dbexec.c b/sys/contrib/dev/acpica/components/debugger/dbexec.c index 79c0ee9..c8a4112 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbexec.c +++ b/sys/contrib/dev/acpica/components/debugger/dbexec.c @@ -433,15 +433,15 @@ AcpiDbExecute ( } else { - NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); + NameString = ACPI_ALLOCATE (strlen (Name) + 1); if (!NameString) { return; } - ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); + memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); - ACPI_STRCPY (NameString, Name); + strcpy (NameString, Name); AcpiUtStrupr (NameString); AcpiGbl_DbMethodInfo.Name = NameString; AcpiGbl_DbMethodInfo.Args = Args; @@ -669,8 +669,8 @@ AcpiDbCreateExecutionThreads ( /* Get the arguments */ - NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); - NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); + NumThreads = strtoul (NumThreadsArg, NULL, 0); + NumLoops = strtoul (NumLoopsArg, NULL, 0); if (!NumThreads || !NumLoops) { @@ -714,7 +714,7 @@ AcpiDbCreateExecutionThreads ( return; } - ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); + memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); /* Array to store IDs of threads */ @@ -729,7 +729,7 @@ AcpiDbCreateExecutionThreads ( (void) AcpiOsDeleteSemaphore (InfoGate); return; } - ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); + memset (AcpiGbl_DbMethodInfo.Threads, 0, Size); /* Setup the context to be passed to each thread */ diff --git a/sys/contrib/dev/acpica/components/debugger/dbfileio.c b/sys/contrib/dev/acpica/components/debugger/dbfileio.c index 59a9a52..f39fac1 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbfileio.c +++ b/sys/contrib/dev/acpica/components/debugger/dbfileio.c @@ -112,7 +112,7 @@ AcpiDbOpenDebugFile ( } AcpiOsPrintf ("Debug output file %s opened\n", Name); - ACPI_STRNCPY (AcpiGbl_DbDebugFilename, Name, + strncpy (AcpiGbl_DbDebugFilename, Name, sizeof (AcpiGbl_DbDebugFilename)); AcpiGbl_DbOutputToFile = TRUE; diff --git a/sys/contrib/dev/acpica/components/debugger/dbhistry.c b/sys/contrib/dev/acpica/components/debugger/dbhistry.c index e945779..6674fdb 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbhistry.c +++ b/sys/contrib/dev/acpica/components/debugger/dbhistry.c @@ -92,7 +92,7 @@ AcpiDbAddToHistory ( /* Put command into the next available slot */ - CmdLen = (UINT16) ACPI_STRLEN (CommandLine); + CmdLen = (UINT16) strlen (CommandLine); if (!CmdLen) { return; @@ -100,7 +100,7 @@ AcpiDbAddToHistory ( if (AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].Command != NULL) { - BufferLen = (UINT16) ACPI_STRLEN ( + BufferLen = (UINT16) strlen ( AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].Command); if (CmdLen > BufferLen) { @@ -116,7 +116,7 @@ AcpiDbAddToHistory ( AcpiOsAllocate (CmdLen + 1); } - ACPI_STRCPY (AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].Command, + strcpy (AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].Command, CommandLine); AcpiGbl_HistoryBuffer[AcpiGbl_NextHistoryIndex].CmdNum = @@ -217,7 +217,7 @@ AcpiDbGetFromHistory ( else { - CmdNum = ACPI_STRTOUL (CommandNumArg, NULL, 0); + CmdNum = strtoul (CommandNumArg, NULL, 0); } return (AcpiDbGetHistoryByIndex (CmdNum)); diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c index 623bc48..f7e59d8 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbinput.c +++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c @@ -361,7 +361,7 @@ AcpiDbMatchCommandHelp ( while ((*Command) && (*Invocation) && (*Invocation != ' ')) { - if (ACPI_TOLOWER (*Command) != ACPI_TOLOWER (*Invocation)) + if (tolower ((int) *Command) != tolower ((int) *Invocation)) { return (FALSE); } @@ -702,7 +702,7 @@ AcpiDbMatchCommand ( for (i = CMD_FIRST_VALID; AcpiGbl_DbCommands[i].Name; i++) { - if (ACPI_STRSTR (AcpiGbl_DbCommands[i].Name, UserCommand) == + if (strstr (AcpiGbl_DbCommands[i].Name, UserCommand) == AcpiGbl_DbCommands[i].Name) { return (i); @@ -946,7 +946,7 @@ AcpiDbCommandDispatch ( else if (ParamCount == 2) { Temp = AcpiGbl_DbConsoleDebugLevel; - AcpiGbl_DbConsoleDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1], + AcpiGbl_DbConsoleDebugLevel = strtoul (AcpiGbl_DbArgs[1], NULL, 16); AcpiOsPrintf ( "Debug Level for console output was %8.8lX, now %8.8lX\n", @@ -955,7 +955,7 @@ AcpiDbCommandDispatch ( else { Temp = AcpiGbl_DbDebugLevel; - AcpiGbl_DbDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1], NULL, 16); + AcpiGbl_DbDebugLevel = strtoul (AcpiGbl_DbArgs[1], NULL, 16); AcpiOsPrintf ( "Debug Level for file output was %8.8lX, now %8.8lX\n", Temp, AcpiGbl_DbDebugLevel); @@ -994,7 +994,7 @@ AcpiDbCommandDispatch ( case CMD_NOTIFY: - Temp = ACPI_STRTOUL (AcpiGbl_DbArgs[2], NULL, 0); + Temp = strtoul (AcpiGbl_DbArgs[2], NULL, 0); AcpiDbSendNotify (AcpiGbl_DbArgs[1], Temp); break; diff --git a/sys/contrib/dev/acpica/components/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c index 5224854..65266c1 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbmethod.c +++ b/sys/contrib/dev/acpica/components/debugger/dbmethod.c @@ -89,7 +89,7 @@ AcpiDbSetMethodBreakpoint ( /* Get and verify the breakpoint address */ - Address = ACPI_STRTOUL (Location, NULL, 16); + Address = strtoul (Location, NULL, 16); if (Address <= Op->Common.AmlOffset) { AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", @@ -174,7 +174,7 @@ AcpiDbSetMethodData ( return; } - Value = ACPI_STRTOUL (ValueArg, NULL, 16); + Value = strtoul (ValueArg, NULL, 16); if (Type == 'N') { @@ -196,7 +196,7 @@ AcpiDbSetMethodData ( /* Get the index and value */ - Index = ACPI_STRTOUL (IndexArg, NULL, 16); + Index = strtoul (IndexArg, NULL, 16); WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); if (!WalkState) @@ -304,7 +304,7 @@ AcpiDbDisassembleAml ( if (Statements) { - NumStatements = ACPI_STRTOUL (Statements, NULL, 0); + NumStatements = strtoul (Statements, NULL, 0); } #ifdef ACPI_DISASSEMBLER diff --git a/sys/contrib/dev/acpica/components/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c index d749b1d..67cf517 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbnames.c +++ b/sys/contrib/dev/acpica/components/debugger/dbnames.c @@ -248,7 +248,7 @@ AcpiDbDumpNamespace ( if (DepthArg) { - MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); + MaxDepth = strtoul (DepthArg, NULL, 0); } } @@ -319,13 +319,13 @@ AcpiDbDumpNamespaceByOwner ( ACPI_OWNER_ID OwnerId; - OwnerId = (ACPI_OWNER_ID) ACPI_STRTOUL (OwnerArg, NULL, 0); + OwnerId = (ACPI_OWNER_ID) strtoul (OwnerArg, NULL, 0); /* Now we can check for the depth argument */ if (DepthArg) { - MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); + MaxDepth = strtoul (DepthArg, NULL, 0); } AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); @@ -426,7 +426,7 @@ AcpiDbFindNameInNamespace ( char *AcpiNamePtr = AcpiName; - if (ACPI_STRLEN (NameArg) > 4) + if (strlen (NameArg) > 4) { AcpiOsPrintf ("Name must be no longer than 4 characters\n"); return (AE_OK); @@ -830,7 +830,7 @@ AcpiDbFindReferences ( /* Convert string to object pointer */ - Address = ACPI_STRTOUL (ObjectArg, NULL, 16); + Address = strtoul (ObjectArg, NULL, 16); ObjDesc = ACPI_TO_POINTER (Address); /* Search all nodes in namespace */ diff --git a/sys/contrib/dev/acpica/components/debugger/dbtest.c b/sys/contrib/dev/acpica/components/debugger/dbtest.c index ab14984..ce3347c 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbtest.c +++ b/sys/contrib/dev/acpica/components/debugger/dbtest.c @@ -646,7 +646,7 @@ AcpiDbTestBufferType ( * count is not an integral number of bytes. Zero out the * unused bits. */ - ACPI_MEMSET (Buffer, BUFFER_FILL_VALUE, ByteLength); + memset (Buffer, BUFFER_FILL_VALUE, ByteLength); ExtraBits = BitLength % 8; if (ExtraBits) { @@ -671,7 +671,7 @@ AcpiDbTestBufferType ( goto Exit; } - if (ACPI_MEMCMP (Temp2->Buffer.Pointer, Buffer, ByteLength)) + if (memcmp (Temp2->Buffer.Pointer, Buffer, ByteLength)) { AcpiOsPrintf (" MISMATCH 2: New buffer value"); } @@ -695,7 +695,7 @@ AcpiDbTestBufferType ( goto Exit; } - if (ACPI_MEMCMP (Temp1->Buffer.Pointer, Temp3->Buffer.Pointer, ByteLength)) + if (memcmp (Temp1->Buffer.Pointer, Temp3->Buffer.Pointer, ByteLength)) { AcpiOsPrintf (" MISMATCH 3: While restoring original buffer"); } @@ -751,7 +751,7 @@ AcpiDbTestStringType ( /* Write a new value */ WriteValue.Type = ACPI_TYPE_STRING; - WriteValue.String.Length = ACPI_STRLEN (ValueToWrite); + WriteValue.String.Length = strlen (ValueToWrite); WriteValue.String.Pointer = ValueToWrite; Status = AcpiDbWriteToObject (Node, &WriteValue); @@ -768,7 +768,7 @@ AcpiDbTestStringType ( goto Exit; } - if (ACPI_STRCMP (Temp2->String.Pointer, ValueToWrite)) + if (strcmp (Temp2->String.Pointer, ValueToWrite)) { AcpiOsPrintf (" MISMATCH 2: %s, expecting %s", Temp2->String.Pointer, ValueToWrite); @@ -776,7 +776,7 @@ AcpiDbTestStringType ( /* Write back the original value */ - WriteValue.String.Length = ACPI_STRLEN (Temp1->String.Pointer); + WriteValue.String.Length = strlen (Temp1->String.Pointer); WriteValue.String.Pointer = Temp1->String.Pointer; Status = AcpiDbWriteToObject (Node, &WriteValue); @@ -793,7 +793,7 @@ AcpiDbTestStringType ( goto Exit; } - if (ACPI_STRCMP (Temp1->String.Pointer, Temp3->String.Pointer)) + if (strcmp (Temp1->String.Pointer, Temp3->String.Pointer)) { AcpiOsPrintf (" MISMATCH 3: %s, expecting %s", Temp3->String.Pointer, Temp1->String.Pointer); @@ -926,7 +926,7 @@ AcpiDbWriteToObject ( /* Copy the incoming user parameter */ - ACPI_MEMCPY (&Params[1], Value, sizeof (ACPI_OBJECT)); + memcpy (&Params[1], Value, sizeof (ACPI_OBJECT)); ParamObjects.Count = 2; ParamObjects.Pointer = Params; @@ -970,7 +970,7 @@ AcpiDbEvaluateAllPredefinedNames ( if (CountArg) { - Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); + Info.MaxCount = strtoul (CountArg, NULL, 0); } /* Search all nodes in namespace */ @@ -1077,7 +1077,7 @@ AcpiDbEvaluateOnePredefinedName ( case ACPI_TYPE_STRING: ThisParam->String.Pointer = "This is the default argument string"; - ThisParam->String.Length = ACPI_STRLEN (ThisParam->String.Pointer); + ThisParam->String.Length = strlen (ThisParam->String.Pointer); break; case ACPI_TYPE_BUFFER: diff --git a/sys/contrib/dev/acpica/components/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c index 5db98e1..eeb5f82 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbutils.c +++ b/sys/contrib/dev/acpica/components/debugger/dbutils.c @@ -96,7 +96,7 @@ AcpiDbMatchArgument ( for (i = 0; Arguments[i].Name; i++) { - if (ACPI_STRSTR (Arguments[i].Name, UserArgument) == Arguments[i].Name) + if (strstr (Arguments[i].Name, UserArgument) == Arguments[i].Name) { return (i); } @@ -375,7 +375,7 @@ AcpiDbUint32ToHexString ( if (Value == 0) { - ACPI_STRCPY (Buffer, "0"); + strcpy (Buffer, "0"); return; } diff --git a/sys/contrib/dev/acpica/components/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c index d72ee5e..6609962 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbxface.c +++ b/sys/contrib/dev/acpica/components/debugger/dbxface.c @@ -435,7 +435,7 @@ AcpiDbInitialize ( { return_ACPI_STATUS (AE_NO_MEMORY); } - ACPI_MEMSET (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE); + memset (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE); /* Initial scope is the root */ diff --git a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c index 15b7e87..fbd8f0b 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c @@ -205,7 +205,7 @@ AcpiDmDisasmByteList ( } BufChar = ByteData[CurrentIndex]; - if (ACPI_IS_PRINT (BufChar)) + if (isprint (BufChar)) { AcpiOsPrintf ("%c", BufChar); } @@ -554,7 +554,7 @@ AcpiDmIsStringBuffer ( * they will be handled in the string output routine */ - if (!ACPI_IS_PRINT (ByteData[i])) + if (!isprint (ByteData[i])) { return (FALSE); } @@ -836,7 +836,7 @@ AcpiDmUnicode ( { AcpiOsPrintf ("\\%c", OutputValue); } - else if (!ACPI_IS_PRINT (OutputValue)) + else if (!isprint (OutputValue)) { AcpiOsPrintf ("\\x%2.2X", OutputValue); } @@ -902,7 +902,7 @@ AcpiDmGetHardwareIdType ( for (i = 0; i < 3; i++) { if (!ACPI_IS_ASCII (Prefix[i]) || - !ACPI_IS_ALPHA (Prefix[i])) + !isalpha (Prefix[i])) { return; } diff --git a/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c b/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c index b66dbed..11814a4 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c @@ -337,23 +337,70 @@ AcpiDmCheckForSymbolicOpcode ( */ AcpiDmPromoteTarget (Op, Target); - /* - * Check for possible conversion to a "Compound Assignment". - * - * Determine if either operand is the same as the target - * and display compound assignment operator and other operand. - */ - if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) || - (AcpiDmIsTargetAnOperand (Target, Child2, TRUE))) + /* Check operands for conversion to a "Compound Assignment" */ + + switch (Op->Common.AmlOpcode) { - Target->Common.OperatorSymbol = - AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); + /* Commutative operators */ + + case AML_ADD_OP: + case AML_MULTIPLY_OP: + case AML_BIT_AND_OP: + case AML_BIT_OR_OP: + case AML_BIT_XOR_OP: + /* + * For the commutative operators, we can convert to a + * compound statement only if at least one (either) operand + * is the same as the target. + * + * Add (A, B, A) --> A += B + * Add (B, A, A) --> A += B + * Add (B, C, A) --> A = (B + C) + */ + if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) || + (AcpiDmIsTargetAnOperand (Target, Child2, TRUE))) + { + Target->Common.OperatorSymbol = + AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); - /* Convert operator to compound assignment */ + /* Convert operator to compound assignment */ - Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND; - Child1->Common.OperatorSymbol = NULL; - return (TRUE); + Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND; + Child1->Common.OperatorSymbol = NULL; + return (TRUE); + } + break; + + /* Non-commutative operators */ + + case AML_SUBTRACT_OP: + case AML_DIVIDE_OP: + case AML_MOD_OP: + case AML_SHIFT_LEFT_OP: + case AML_SHIFT_RIGHT_OP: + /* + * For the non-commutative operators, we can convert to a + * compound statement only if the target is the same as the + * first operand. + * + * Subtract (A, B, A) --> A -= B + * Subtract (B, A, A) --> A = (B - A) + */ + if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE))) + { + Target->Common.OperatorSymbol = + AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); + + /* Convert operator to compound assignment */ + + Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND; + Child1->Common.OperatorSymbol = NULL; + return (TRUE); + } + break; + + default: + break; } /* @@ -423,8 +470,12 @@ AcpiDmCheckForSymbolicOpcode ( * source so that the target is processed first. */ Target = Child1->Common.Next; - AcpiDmPromoteTarget (Op, Target); + if (!Target) + { + return (FALSE); + } + AcpiDmPromoteTarget (Op, Target); if (!Target->Common.OperatorSymbol) { Target->Common.OperatorSymbol = " = "; @@ -674,7 +725,8 @@ AcpiDmPromoteTarget ( * * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target. * In other words, determine if the optional target is used or - * not. + * not. Note: If Target is NULL, something is seriously wrong, + * probably with the parse tree. * ******************************************************************************/ @@ -683,6 +735,11 @@ AcpiDmIsValidTarget ( ACPI_PARSE_OBJECT *Target) { + if (!Target) + { + return (FALSE); + } + if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && (Target->Common.Value.Arg == NULL)) { diff --git a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c index b10d433..6b7c1f5 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c @@ -269,10 +269,10 @@ AcpiDmPredefinedDescription ( * Note: NameString is guaranteed to be upper case here. */ LastCharIsDigit = - (ACPI_IS_DIGIT (NameString[3])); /* d */ + (isdigit ((int) NameString[3])); /* d */ LastCharsAreHex = - (ACPI_IS_XDIGIT (NameString[2]) && /* xx */ - ACPI_IS_XDIGIT (NameString[3])); + (isxdigit ((int) NameString[2]) && /* xx */ + isxdigit ((int) NameString[3])); switch (NameString[1]) { diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c index d376bb1..81cf410 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c @@ -530,7 +530,7 @@ AcpiDsCreateField ( } } - ACPI_MEMSET (&Info, 0, sizeof (ACPI_CREATE_FIELD_INFO)); + memset (&Info, 0, sizeof (ACPI_CREATE_FIELD_INFO)); /* Second arg is the field flags */ diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c index 62f9bde..921f556 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c @@ -224,7 +224,7 @@ AcpiDsInitializeObjects ( /* Set all init info to zero */ - ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); Info.OwnerId = OwnerId; Info.TableIndex = TableIndex; diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c index 106c6ab..33d0392 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c @@ -348,7 +348,7 @@ AcpiDsBuildInternalBufferObj ( if (ByteList) { - ACPI_MEMCPY (ObjDesc->Buffer.Pointer, ByteList->Named.Data, + memcpy (ObjDesc->Buffer.Pointer, ByteList->Named.Data, ByteListLength); } } @@ -775,7 +775,7 @@ AcpiDsInitObjectFromOp ( case ACPI_TYPE_STRING: ObjDesc->String.Pointer = Op->Common.Value.String; - ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Op->Common.Value.String); + ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String); /* * The string is contained in the ACPI table, don't ever try diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c index a115b2e..9b23c11 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c @@ -605,7 +605,7 @@ AcpiDsCreateOperand ( ObjDesc = AcpiUtCreateStringObject ((ACPI_SIZE) NameLength); - ACPI_STRNCPY (ObjDesc->String.Pointer, NameString, NameLength); + strncpy (ObjDesc->String.Pointer, NameString, NameLength); Status = AE_OK; } else diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c index 8bc425a..755b15e 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dswload.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dswload.c @@ -325,9 +325,18 @@ AcpiDsLoad1BeginOp ( if ((WalkState->Opcode != AML_SCOPE_OP) && (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP))) { - Flags |= ACPI_NS_ERROR_IF_FOUND; - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", - AcpiUtGetTypeName (ObjectType))); + if (WalkState->NamespaceOverride) + { + Flags |= ACPI_NS_OVERRIDE_IF_FOUND; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n", + AcpiUtGetTypeName (ObjectType))); + } + else + { + Flags |= ACPI_NS_ERROR_IF_FOUND; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", + AcpiUtGetTypeName (ObjectType))); + } } else { diff --git a/sys/contrib/dev/acpica/components/events/evgpe.c b/sys/contrib/dev/acpica/components/events/evgpe.c index 99043ad..0083e60 100644 --- a/sys/contrib/dev/acpica/components/events/evgpe.c +++ b/sys/contrib/dev/acpica/components/events/evgpe.c @@ -104,6 +104,7 @@ AcpiEvUpdateGpeEnableMask ( { ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); } + GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun; return_ACPI_STATUS (AE_OK); } @@ -141,7 +142,7 @@ AcpiEvEnableGpe ( /* Enable the requested GPE */ - Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE_SAVE); + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); return_ACPI_STATUS (Status); } @@ -231,7 +232,7 @@ AcpiEvRemoveGpeReference ( Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); if (ACPI_SUCCESS (Status)) { - Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE_SAVE); + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); } if (ACPI_FAILURE (Status)) diff --git a/sys/contrib/dev/acpica/components/events/evgpeinit.c b/sys/contrib/dev/acpica/components/events/evgpeinit.c index 0e53a1d..63a4c4a 100644 --- a/sys/contrib/dev/acpica/components/events/evgpeinit.c +++ b/sys/contrib/dev/acpica/components/events/evgpeinit.c @@ -395,7 +395,7 @@ AcpiEvMatchGpeMethod ( /* 4) The last two characters of the name are the hex GPE Number */ - GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); + GpeNumber = strtoul (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ diff --git a/sys/contrib/dev/acpica/components/executer/exconfig.c b/sys/contrib/dev/acpica/components/executer/exconfig.c index 0627f99..96188e6 100644 --- a/sys/contrib/dev/acpica/components/executer/exconfig.c +++ b/sys/contrib/dev/acpica/components/executer/exconfig.c @@ -515,7 +515,7 @@ AcpiExLoadOp ( return_ACPI_STATUS (AE_NO_MEMORY); } - ACPI_MEMCPY (Table, TableHeader, Length); + memcpy (Table, TableHeader, Length); break; default: diff --git a/sys/contrib/dev/acpica/components/executer/exconvrt.c b/sys/contrib/dev/acpica/components/executer/exconvrt.c index 50ccf26..ac881cb 100644 --- a/sys/contrib/dev/acpica/components/executer/exconvrt.c +++ b/sys/contrib/dev/acpica/components/executer/exconvrt.c @@ -251,7 +251,7 @@ AcpiExConvertToBuffer ( /* Copy the integer to the buffer, LSB first */ NewBuf = ReturnDesc->Buffer.Pointer; - ACPI_MEMCPY (NewBuf, + memcpy (NewBuf, &ObjDesc->Integer.Value, AcpiGbl_IntegerByteWidth); break; @@ -276,7 +276,7 @@ AcpiExConvertToBuffer ( /* Copy the string to the buffer */ NewBuf = ReturnDesc->Buffer.Pointer; - ACPI_STRNCPY ((char *) NewBuf, (char *) ObjDesc->String.Pointer, + strncpy ((char *) NewBuf, (char *) ObjDesc->String.Pointer, ObjDesc->String.Length); break; diff --git a/sys/contrib/dev/acpica/components/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c index 5e98fd5..d174ccd 100644 --- a/sys/contrib/dev/acpica/components/executer/exdebug.c +++ b/sys/contrib/dev/acpica/components/executer/exdebug.c @@ -81,6 +81,8 @@ AcpiExDoDebugObject ( { UINT32 i; UINT32 Timer; + ACPI_OPERAND_OBJECT *ObjectDesc; + UINT32 Value; ACPI_FUNCTION_TRACE_PTR (ExDoDebugObject, SourceDesc); @@ -267,8 +269,37 @@ AcpiExDoDebugObject ( } else { - AcpiExDoDebugObject (SourceDesc->Reference.Object, - Level+4, 0); + ObjectDesc = SourceDesc->Reference.Object; + Value = SourceDesc->Reference.Value; + + switch (ObjectDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("Buffer[%u] = 0x%2.2X\n", + Value, *SourceDesc->Reference.IndexPointer); + break; + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("String[%u] = \"%c\" (0x%2.2X)\n", + Value, *SourceDesc->Reference.IndexPointer, + *SourceDesc->Reference.IndexPointer); + break; + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("Package[%u] = ", Value); + AcpiExDoDebugObject (*SourceDesc->Reference.Where, + Level+4, 0); + break; + + default: + + AcpiOsPrintf ("Unknown Reference object type %X\n", + ObjectDesc->Common.Type); + break; + } } } break; diff --git a/sys/contrib/dev/acpica/components/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c index 622dc14..1a14d38 100644 --- a/sys/contrib/dev/acpica/components/executer/exdump.c +++ b/sys/contrib/dev/acpica/components/executer/exdump.c @@ -238,7 +238,7 @@ static ACPI_EXDUMP_INFO AcpiExDumpIndexField[5] = {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (IndexField.DataObj), "Data Object"} }; -static ACPI_EXDUMP_INFO AcpiExDumpReference[8] = +static ACPI_EXDUMP_INFO AcpiExDumpReference[9] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpReference), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Reference.Class), "Class"}, @@ -247,6 +247,7 @@ static ACPI_EXDUMP_INFO AcpiExDumpReference[8] = {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Object), "Object Desc"}, {ACPI_EXD_NODE, ACPI_EXD_OFFSET (Reference.Node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Where), "Where"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.IndexPointer), "Index Pointer"}, {ACPI_EXD_REFERENCE,0, NULL} }; @@ -1053,16 +1054,18 @@ AcpiExDumpReferenceObj ( { if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) { - AcpiOsPrintf (" Target: %p", ObjDesc->Reference.Object); + AcpiOsPrintf ("%22s %p", "Target :", + ObjDesc->Reference.Object); if (ObjDesc->Reference.Class == ACPI_REFCLASS_TABLE) { - AcpiOsPrintf (" Table Index: %X\n", ObjDesc->Reference.Value); + AcpiOsPrintf (" Table Index: %X\n", + ObjDesc->Reference.Value); } else { - AcpiOsPrintf (" Target: %p [%s]\n", ObjDesc->Reference.Object, + AcpiOsPrintf (" [%s]\n", AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) - ObjDesc->Reference.Object)->Common.Type)); + ObjDesc->Reference.Object)->Common.Type)); } } else diff --git a/sys/contrib/dev/acpica/components/executer/exfield.c b/sys/contrib/dev/acpica/components/executer/exfield.c index 836a378..ad2d05a 100644 --- a/sys/contrib/dev/acpica/components/executer/exfield.c +++ b/sys/contrib/dev/acpica/components/executer/exfield.c @@ -460,7 +460,7 @@ AcpiExWriteDataToField ( } Buffer = BufferDesc->Buffer.Pointer; - ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, Length); + memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); /* Lock entire transaction if requested */ diff --git a/sys/contrib/dev/acpica/components/executer/exfldio.c b/sys/contrib/dev/acpica/components/executer/exfldio.c index 2908da4..31727de 100644 --- a/sys/contrib/dev/acpica/components/executer/exfldio.c +++ b/sys/contrib/dev/acpica/components/executer/exfldio.c @@ -456,7 +456,7 @@ AcpiExFieldDatumIo ( * Copy the data from the source buffer. * Length is the field width in bytes. */ - ACPI_MEMCPY (Value, + memcpy (Value, (ObjDesc->BufferField.BufferObj)->Buffer.Pointer + ObjDesc->BufferField.BaseByteOffset + FieldDatumByteOffset, @@ -468,7 +468,7 @@ AcpiExFieldDatumIo ( * Copy the data to the target buffer. * Length is the field width in bytes. */ - ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer + + memcpy ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer + ObjDesc->BufferField.BaseByteOffset + FieldDatumByteOffset, Value, ObjDesc->CommonField.AccessByteWidth); @@ -748,7 +748,7 @@ AcpiExExtractFromField ( return_ACPI_STATUS (AE_BUFFER_OVERFLOW); } - ACPI_MEMSET (Buffer, 0, BufferLength); + memset (Buffer, 0, BufferLength); AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth); /* Handle the simple case here */ @@ -765,7 +765,7 @@ AcpiExExtractFromField ( /* Use RawDatum (UINT64) to handle buffers < 64 bits */ Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ); - ACPI_MEMCPY (Buffer, &RawDatum, BufferLength); + memcpy (Buffer, &RawDatum, BufferLength); } return_ACPI_STATUS (Status); @@ -835,7 +835,7 @@ AcpiExExtractFromField ( /* Write merged datum to target buffer */ - ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum, + memcpy (((char *) Buffer) + BufferOffset, &MergedDatum, ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, BufferLength - BufferOffset)); @@ -853,7 +853,7 @@ AcpiExExtractFromField ( /* Write the last datum to the buffer */ - ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum, + memcpy (((char *) Buffer) + BufferOffset, &MergedDatum, ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, BufferLength - BufferOffset)); @@ -926,7 +926,7 @@ AcpiExInsertIntoField ( * at Byte zero. All unused (upper) bytes of the * buffer will be 0. */ - ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength); + memcpy ((char *) NewBuffer, (char *) Buffer, BufferLength); Buffer = NewBuffer; BufferLength = RequiredLength; } @@ -969,7 +969,7 @@ AcpiExInsertIntoField ( /* Get initial Datum from the input buffer */ - ACPI_MEMCPY (&RawDatum, Buffer, + memcpy (&RawDatum, Buffer, ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, BufferLength - BufferOffset)); @@ -1021,7 +1021,7 @@ AcpiExInsertIntoField ( /* Get the next input datum from the buffer */ BufferOffset += ObjDesc->CommonField.AccessByteWidth; - ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset, + memcpy (&RawDatum, ((char *) Buffer) + BufferOffset, ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, BufferLength - BufferOffset)); diff --git a/sys/contrib/dev/acpica/components/executer/exmisc.c b/sys/contrib/dev/acpica/components/executer/exmisc.c index d4e1a3b..df02e03 100644 --- a/sys/contrib/dev/acpica/components/executer/exmisc.c +++ b/sys/contrib/dev/acpica/components/executer/exmisc.c @@ -225,8 +225,8 @@ AcpiExConcatTemplate ( * EndTag descriptor is copied from Operand1. */ NewBuf = ReturnDesc->Buffer.Pointer; - ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0); - ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); + memcpy (NewBuf, Operand0->Buffer.Pointer, Length0); + memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ @@ -340,12 +340,12 @@ AcpiExDoConcatenate ( /* Copy the first integer, LSB first */ - ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, + memcpy (NewBuf, &Operand0->Integer.Value, AcpiGbl_IntegerByteWidth); /* Copy the second integer (LSB first) after the first */ - ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, + memcpy (NewBuf + AcpiGbl_IntegerByteWidth, &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); break; @@ -367,8 +367,8 @@ AcpiExDoConcatenate ( /* Concatenate the strings */ - ACPI_STRCPY (NewBuf, Operand0->String.Pointer); - ACPI_STRCPY (NewBuf + Operand0->String.Length, + strcpy (NewBuf, Operand0->String.Pointer); + strcpy (NewBuf + Operand0->String.Length, LocalOperand1->String.Pointer); break; @@ -389,9 +389,9 @@ AcpiExDoConcatenate ( /* Concatenate the buffers */ - ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, + memcpy (NewBuf, Operand0->Buffer.Pointer, Operand0->Buffer.Length); - ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, + memcpy (NewBuf + Operand0->Buffer.Length, LocalOperand1->Buffer.Pointer, LocalOperand1->Buffer.Length); break; @@ -712,7 +712,7 @@ AcpiExDoLogicalOp ( /* Lexicographic compare: compare the data bytes */ - Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer, + Compare = memcmp (Operand0->Buffer.Pointer, LocalOperand1->Buffer.Pointer, (Length0 > Length1) ? Length1 : Length0); diff --git a/sys/contrib/dev/acpica/components/executer/exnames.c b/sys/contrib/dev/acpica/components/executer/exnames.c index b213165..a6c9e6b 100644 --- a/sys/contrib/dev/acpica/components/executer/exnames.c +++ b/sys/contrib/dev/acpica/components/executer/exnames.c @@ -221,7 +221,7 @@ AcpiExNameSegment ( if (NameString) { - ACPI_STRCAT (NameString, CharBuf); + strcat (NameString, CharBuf); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Appended to - %s\n", NameString)); } diff --git a/sys/contrib/dev/acpica/components/executer/exoparg2.c b/sys/contrib/dev/acpica/components/executer/exoparg2.c index da1eb6c..e11c0b3 100644 --- a/sys/contrib/dev/acpica/components/executer/exoparg2.c +++ b/sys/contrib/dev/acpica/components/executer/exoparg2.c @@ -368,7 +368,7 @@ AcpiExOpcode_2A_1T_1R ( * Copy the raw buffer data with no transform. * (NULL terminated already) */ - ACPI_MEMCPY (ReturnDesc->String.Pointer, + memcpy (ReturnDesc->String.Pointer, Operand[0]->Buffer.Pointer, Length); break; @@ -412,6 +412,8 @@ AcpiExOpcode_2A_1T_1R ( } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + ReturnDesc->Reference.IndexPointer = + &(Operand[0]->Buffer.Pointer [Index]); break; case ACPI_TYPE_BUFFER: @@ -423,6 +425,8 @@ AcpiExOpcode_2A_1T_1R ( } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + ReturnDesc->Reference.IndexPointer = + &(Operand[0]->Buffer.Pointer [Index]); break; case ACPI_TYPE_PACKAGE: @@ -434,7 +438,8 @@ AcpiExOpcode_2A_1T_1R ( } ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; - ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index]; + ReturnDesc->Reference.Where = + &Operand[0]->Package.Elements [Index]; break; default: diff --git a/sys/contrib/dev/acpica/components/executer/exoparg3.c b/sys/contrib/dev/acpica/components/executer/exoparg3.c index da873c3..54636bc 100644 --- a/sys/contrib/dev/acpica/components/executer/exoparg3.c +++ b/sys/contrib/dev/acpica/components/executer/exoparg3.c @@ -261,7 +261,7 @@ AcpiExOpcode_3A_1T_1R ( { /* We have a buffer, copy the portion requested */ - ACPI_MEMCPY (Buffer, Operand[0]->String.Pointer + Index, + memcpy (Buffer, Operand[0]->String.Pointer + Index, Length); } diff --git a/sys/contrib/dev/acpica/components/executer/exregion.c b/sys/contrib/dev/acpica/components/executer/exregion.c index 59b4612..6bfdf7b 100644 --- a/sys/contrib/dev/acpica/components/executer/exregion.c +++ b/sys/contrib/dev/acpica/components/executer/exregion.c @@ -558,13 +558,13 @@ AcpiExDataTableSpaceHandler ( { case ACPI_READ: - ACPI_MEMCPY (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address), + memcpy (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address), ACPI_DIV_8 (BitWidth)); break; case ACPI_WRITE: - ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value), + memcpy (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value), ACPI_DIV_8 (BitWidth)); break; diff --git a/sys/contrib/dev/acpica/components/executer/exstorob.c b/sys/contrib/dev/acpica/components/executer/exstorob.c index c238310..683bfce 100644 --- a/sys/contrib/dev/acpica/components/executer/exstorob.c +++ b/sys/contrib/dev/acpica/components/executer/exstorob.c @@ -109,8 +109,8 @@ AcpiExStoreBufferToBuffer ( { /* Clear existing buffer and copy in the new one */ - ACPI_MEMSET (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length); - ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer, Length); + memset (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length); + memcpy (TargetDesc->Buffer.Pointer, Buffer, Length); #ifdef ACPI_OBSOLETE_BEHAVIOR /* @@ -139,7 +139,7 @@ AcpiExStoreBufferToBuffer ( { /* Truncate the source, copy only what will fit */ - ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer, + memcpy (TargetDesc->Buffer.Pointer, Buffer, TargetDesc->Buffer.Length); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, @@ -203,9 +203,9 @@ AcpiExStoreStringToString ( * String will fit in existing non-static buffer. * Clear old string and copy in the new one */ - ACPI_MEMSET (TargetDesc->String.Pointer, 0, + memset (TargetDesc->String.Pointer, 0, (ACPI_SIZE) TargetDesc->String.Length + 1); - ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length); + memcpy (TargetDesc->String.Pointer, Buffer, Length); } else { @@ -229,7 +229,7 @@ AcpiExStoreStringToString ( } TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; - ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length); + memcpy (TargetDesc->String.Pointer, Buffer, Length); } /* Set the new target length */ diff --git a/sys/contrib/dev/acpica/components/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c index a55b171..1cd60fa 100644 --- a/sys/contrib/dev/acpica/components/executer/exutils.c +++ b/sys/contrib/dev/acpica/components/executer/exutils.c @@ -433,6 +433,43 @@ AcpiExIntegerToString ( /******************************************************************************* * + * FUNCTION: AcpiExPciClsToString + * + * PARAMETERS: OutString - Where to put the converted string (7 bytes) + * PARAMETERS: ClassCode - PCI class code to be converted (3 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert 3-bytes PCI class code to string representation. + * Return buffer must be large enough to hold the string. The + * string returned is always exactly of length + * ACPI_PCICLS_STRING_SIZE (includes null terminator). + * + ******************************************************************************/ + +void +AcpiExPciClsToString ( + char *OutString, + UINT8 ClassCode[3]) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* All 3 bytes are hexadecimal */ + + OutString[0] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 4); + OutString[1] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 0); + OutString[2] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 4); + OutString[3] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 0); + OutString[4] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 4); + OutString[5] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 0); + OutString[6] = 0; +} + + +/******************************************************************************* + * * FUNCTION: AcpiIsValidSpaceId * * PARAMETERS: SpaceId - ID to be validated diff --git a/sys/contrib/dev/acpica/components/hardware/hwgpe.c b/sys/contrib/dev/acpica/components/hardware/hwgpe.c index 093ba80..c293bef 100644 --- a/sys/contrib/dev/acpica/components/hardware/hwgpe.c +++ b/sys/contrib/dev/acpica/components/hardware/hwgpe.c @@ -97,6 +97,8 @@ AcpiHwGetGpeRegisterBit ( * RETURN: Status * * DESCRIPTION: Enable or disable a single GPE in the parent enable register. + * The EnableMask field of the involved GPE register must be + * updated by the caller if necessary. * ******************************************************************************/ @@ -133,7 +135,7 @@ AcpiHwLowSetGpe ( /* Set or clear just the bit that corresponds to this GPE */ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); - switch (Action & ~ACPI_GPE_SAVE_MASK) + switch (Action) { case ACPI_GPE_CONDITIONAL_ENABLE: @@ -165,10 +167,6 @@ AcpiHwLowSetGpe ( /* Write the updated enable mask */ Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); - if (ACPI_SUCCESS (Status) && (Action & ACPI_GPE_SAVE_MASK)) - { - GpeRegisterInfo->EnableMask = (UINT8) EnableMask; - } return (Status); } @@ -334,11 +332,8 @@ AcpiHwGpeEnableWrite ( ACPI_STATUS Status; + GpeRegisterInfo->EnableMask = EnableMask; Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); - if (ACPI_SUCCESS (Status)) - { - GpeRegisterInfo->EnableMask = EnableMask; - } return (Status); } diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c index 8d5ba97..5610398 100644 --- a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c +++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c @@ -51,6 +51,14 @@ /* Local prototypes */ +#if (!ACPI_REDUCED_HARDWARE) +static ACPI_STATUS +AcpiHwSetFirmwareWakingVector ( + ACPI_TABLE_FACS *Facs, + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64); +#endif + static ACPI_STATUS AcpiHwSleepDispatch ( UINT8 SleepState, @@ -77,29 +85,33 @@ static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] = /* * These functions are removed for the ACPI_REDUCED_HARDWARE case: * AcpiSetFirmwareWakingVector - * AcpiSetFirmwareWakingVector64 * AcpiEnterSleepStateS4bios */ #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * - * FUNCTION: AcpiSetFirmwareWakingVector + * FUNCTION: AcpiHwSetFirmwareWakingVector * - * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode - * entry point. + * PARAMETERS: Facs - Pointer to FACS table + * PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point + * PhysicalAddress64 - 64-bit physical address of ACPI protected + * entry point * * RETURN: Status * - * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS + * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS * ******************************************************************************/ -ACPI_STATUS -AcpiSetFirmwareWakingVector ( - UINT32 PhysicalAddress) +static ACPI_STATUS +AcpiHwSetFirmwareWakingVector ( + ACPI_TABLE_FACS *Facs, + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64) { - ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); + ACPI_FUNCTION_TRACE (AcpiHwSetFirmwareWakingVector); /* @@ -112,60 +124,73 @@ AcpiSetFirmwareWakingVector ( /* Set the 32-bit vector */ - AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; + Facs->FirmwareWakingVector = (UINT32) PhysicalAddress; - /* Clear the 64-bit vector if it exists */ - - if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1)) + if (Facs->Length > 32) { - AcpiGbl_FACS->XFirmwareWakingVector = 0; + if (Facs->Version >= 1) + { + /* Set the 64-bit vector */ + + Facs->XFirmwareWakingVector = PhysicalAddress64; + } + else + { + /* Clear the 64-bit vector if it exists */ + + Facs->XFirmwareWakingVector = 0; + } } return_ACPI_STATUS (AE_OK); } -ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) - -#if ACPI_MACHINE_WIDTH == 64 /******************************************************************************* * - * FUNCTION: AcpiSetFirmwareWakingVector64 + * FUNCTION: AcpiSetFirmwareWakingVector * - * PARAMETERS: PhysicalAddress - 64-bit physical address of ACPI protected - * mode entry point. + * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point + * PhysicalAddress64 - 64-bit physical address of ACPI protected + * entry point * * RETURN: Status * - * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if - * it exists in the table. This function is intended for use with - * 64-bit host operating systems. + * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS * ******************************************************************************/ ACPI_STATUS -AcpiSetFirmwareWakingVector64 ( - UINT64 PhysicalAddress) +AcpiSetFirmwareWakingVector ( + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64) { - ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64); + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); - /* Determine if the 64-bit vector actually exists */ + /* If Hardware Reduced flag is set, there is no FACS */ - if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1)) + if (AcpiGbl_ReducedHardware) { - return_ACPI_STATUS (AE_NOT_EXIST); + return_ACPI_STATUS (AE_OK); } - /* Clear 32-bit vector, set the 64-bit X_ vector */ + if (AcpiGbl_Facs32) + { + (void) AcpiHwSetFirmwareWakingVector (AcpiGbl_Facs32, + PhysicalAddress, PhysicalAddress64); + } + if (AcpiGbl_Facs64) + { + (void) AcpiHwSetFirmwareWakingVector (AcpiGbl_Facs64, + PhysicalAddress, PhysicalAddress64); + } - AcpiGbl_FACS->FirmwareWakingVector = 0; - AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress; return_ACPI_STATUS (AE_OK); } -ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64) -#endif +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) /******************************************************************************* diff --git a/sys/contrib/dev/acpica/components/namespace/nsaccess.c b/sys/contrib/dev/acpica/components/namespace/nsaccess.c index 667b5af..46a64f5 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsaccess.c +++ b/sys/contrib/dev/acpica/components/namespace/nsaccess.c @@ -111,7 +111,7 @@ AcpiNsRootInitialize ( { /* _OSI is optional for now, will be permanent later */ - if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) + if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) { continue; } @@ -191,7 +191,7 @@ AcpiNsRootInitialize ( /* Build an object around the static string */ - ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val); + ObjDesc->String.Length = (UINT32) strlen (Val); ObjDesc->String.Pointer = Val; ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; break; @@ -212,7 +212,7 @@ AcpiNsRootInitialize ( /* Special case for ACPI Global Lock */ - if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0) + if (strcmp (InitVal->Name, "_GL_") == 0) { AcpiGbl_GlobalLockMutex = ObjDesc; @@ -319,7 +319,9 @@ AcpiNsLookup ( return_ACPI_STATUS (AE_BAD_PARAMETER); } - LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); + LocalFlags = Flags & + ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | + ACPI_NS_SEARCH_PARENT); *ReturnNode = ACPI_ENTRY_NOT_FOUND; AcpiGbl_NsLookupCount++; @@ -571,6 +573,13 @@ AcpiNsLookup ( { LocalFlags |= ACPI_NS_ERROR_IF_FOUND; } + + /* Set override flag according to caller */ + + if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) + { + LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND; + } } /* Extract one ACPI name from the front of the pathname */ diff --git a/sys/contrib/dev/acpica/components/namespace/nsconvert.c b/sys/contrib/dev/acpica/components/namespace/nsconvert.c index 091c5cc..99883c2 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsconvert.c +++ b/sys/contrib/dev/acpica/components/namespace/nsconvert.c @@ -202,7 +202,7 @@ AcpiNsConvertToString ( * Copy the raw buffer data with no transform. String is already NULL * terminated at Length+1. */ - ACPI_MEMCPY (NewObject->String.Pointer, + memcpy (NewObject->String.Pointer, OriginalObject->Buffer.Pointer, Length); break; @@ -269,7 +269,7 @@ AcpiNsConvertToBuffer ( return (AE_NO_MEMORY); } - ACPI_MEMCPY (NewObject->Buffer.Pointer, + memcpy (NewObject->Buffer.Pointer, OriginalObject->String.Pointer, OriginalObject->String.Length); break; diff --git a/sys/contrib/dev/acpica/components/namespace/nsdump.c b/sys/contrib/dev/acpica/components/namespace/nsdump.c index 77fb279..f3f3fed 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsdump.c +++ b/sys/contrib/dev/acpica/components/namespace/nsdump.c @@ -122,7 +122,7 @@ AcpiNsPrintPathname ( { for (i = 0; i < 4; i++) { - ACPI_IS_PRINT (Pathname[i]) ? + isprint ((int) Pathname[i]) ? AcpiOsPrintf ("%c", Pathname[i]) : AcpiOsPrintf ("?"); } diff --git a/sys/contrib/dev/acpica/components/namespace/nseval.c b/sys/contrib/dev/acpica/components/namespace/nseval.c index ac1d9a9..fb39171 100644 --- a/sys/contrib/dev/acpica/components/namespace/nseval.c +++ b/sys/contrib/dev/acpica/components/namespace/nseval.c @@ -63,15 +63,14 @@ AcpiNsExecModuleCode ( * * FUNCTION: AcpiNsEvaluate * - * PARAMETERS: Info - Evaluation info block, contains: + * PARAMETERS: Info - Evaluation info block, contains these fields + * and more: * PrefixNode - Prefix or Method/Object Node to execute * RelativePath - Name of method to execute, If NULL, the * Node is the object to execute * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. - * ReturnObject - Where to put method's return value (if - * any). If NULL, no value is returned. * ParameterType - Type of Parameter list * ReturnObject - Where to put method's return value (if * any). If NULL, no value is returned. @@ -463,7 +462,7 @@ AcpiNsExecModuleCode ( /* Initialize the evaluation information block */ - ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); + memset (Info, 0, sizeof (ACPI_EVALUATE_INFO)); Info->PrefixNode = ParentNode; /* diff --git a/sys/contrib/dev/acpica/components/namespace/nsinit.c b/sys/contrib/dev/acpica/components/namespace/nsinit.c index 847bf72..cbfc4a6f 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsinit.c +++ b/sys/contrib/dev/acpica/components/namespace/nsinit.c @@ -105,7 +105,7 @@ AcpiNsInitializeObjects ( /* Set all init info to zero */ - ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); /* Walk entire namespace from the supplied root */ @@ -614,7 +614,7 @@ AcpiNsInitOneDevice ( ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname ( ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI)); - ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); + memset (Info, 0, sizeof (ACPI_EVALUATE_INFO)); Info->PrefixNode = DeviceNode; Info->RelativePathname = METHOD_NAME__INI; Info->Parameters = NULL; diff --git a/sys/contrib/dev/acpica/components/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c index 0f87fa1..7c6d29a 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsparse.c +++ b/sys/contrib/dev/acpica/components/namespace/nsparse.c @@ -129,6 +129,14 @@ AcpiNsOneCompleteParse ( AmlStart, AmlLength, NULL, (UINT8) PassNumber); } + /* Found OSDT table, enable the namespace override feature */ + + if (ACPI_COMPARE_NAME(Table->Signature, ACPI_SIG_OSDT) && + PassNumber == ACPI_IMODE_LOAD_PASS1) + { + WalkState->NamespaceOverride = TRUE; + } + if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c index 410b009..24ac8b4 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c +++ b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c @@ -637,7 +637,7 @@ AcpiNsRepair_HID ( */ for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) { - *Dest = (char) ACPI_TOUPPER (*Source); + *Dest = (char) toupper ((int) *Source); } AcpiUtRemoveReference (ReturnObject); diff --git a/sys/contrib/dev/acpica/components/namespace/nssearch.c b/sys/contrib/dev/acpica/components/namespace/nssearch.c index 9f24f1c..a1e6d1a 100644 --- a/sys/contrib/dev/acpica/components/namespace/nssearch.c +++ b/sys/contrib/dev/acpica/components/namespace/nssearch.c @@ -338,10 +338,42 @@ AcpiNsSearchAndEnter ( * If we found it AND the request specifies that a find is an error, * return the error */ - if ((Status == AE_OK) && - (Flags & ACPI_NS_ERROR_IF_FOUND)) + if (Status == AE_OK) { - Status = AE_ALREADY_EXISTS; + /* The node was found in the namespace */ + + /* + * If the namespace override feature is enabled for this node, + * delete any existing attached sub-object and make the node + * look like a new node that is owned by the override table. + */ + if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Namespace override: %4.4s pass %u type %X Owner %X\n", + ACPI_CAST_PTR(char, &TargetName), InterpreterMode, + (*ReturnNode)->Type, WalkState->OwnerId)); + + AcpiNsDeleteChildren (*ReturnNode); + if (AcpiGbl_RuntimeNamespaceOverride) + { + AcpiUtRemoveReference ((*ReturnNode)->Object); + (*ReturnNode)->Object = NULL; + (*ReturnNode)->OwnerId = WalkState->OwnerId; + } + else + { + AcpiNsRemoveNode (*ReturnNode); + *ReturnNode = ACPI_ENTRY_NOT_FOUND; + } + } + + /* Return an error if we don't expect to find the object */ + + else if (Flags & ACPI_NS_ERROR_IF_FOUND) + { + Status = AE_ALREADY_EXISTS; + } } #ifdef ACPI_ASL_COMPILER diff --git a/sys/contrib/dev/acpica/components/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c index d7320a6..4a59784 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsutils.c +++ b/sys/contrib/dev/acpica/components/namespace/nsutils.c @@ -347,7 +347,7 @@ AcpiNsBuildInternalName ( { /* Convert the character to uppercase and save it */ - Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName); + Result[i] = (char) toupper ((int) *ExternalName); ExternalName++; } } diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c index 93226ef..9b4d2db 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c +++ b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c @@ -758,7 +758,7 @@ AcpiNsGetDeviceCallback ( return (AE_CTRL_DEPTH); } - NoMatch = ACPI_STRCMP (Hid->String, Info->Hid); + NoMatch = strcmp (Hid->String, Info->Hid); ACPI_FREE (Hid); if (NoMatch) @@ -782,7 +782,7 @@ AcpiNsGetDeviceCallback ( Found = FALSE; for (i = 0; i < Cid->Count; i++) { - if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0) + if (strcmp (Cid->Ids[i].String, Info->Hid) == 0) { /* Found a matching CID */ diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c index 804ea94..7ee3fdd 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsxfname.c +++ b/sys/contrib/dev/acpica/components/namespace/nsxfname.c @@ -126,7 +126,7 @@ AcpiGetHandle ( /* Special case for root-only, since we can't search for it */ - if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH)) + if (!strcmp (Pathname, ACPI_NS_ROOT_PATH)) { *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode); return (AE_OK); @@ -271,7 +271,7 @@ AcpiNsCopyDeviceId ( /* Copy actual string and return a pointer to the next string area */ - ACPI_MEMCPY (StringArea, Source->String, Source->Length); + memcpy (StringArea, Source->String, Source->Length); return (StringArea + Source->Length); } @@ -290,7 +290,7 @@ AcpiNsCopyDeviceId ( * control methods (Such as in the case of a device.) * * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB, - * _STA, _ADR, _SxW, and _SxD methods. + * _CLS, _STA, _ADR, _SxW, and _SxD methods. * * Note: Allocates the return buffer, must be freed by the caller. * @@ -307,11 +307,12 @@ AcpiGetObjectInfo ( ACPI_PNP_DEVICE_ID *Hid = NULL; ACPI_PNP_DEVICE_ID *Uid = NULL; ACPI_PNP_DEVICE_ID *Sub = NULL; + ACPI_PNP_DEVICE_ID *Cls = NULL; char *NextIdString; ACPI_OBJECT_TYPE Type; ACPI_NAME Name; UINT8 ParamCount= 0; - UINT8 Valid = 0; + UINT16 Valid = 0; UINT32 InfoSize; UINT32 i; ACPI_STATUS Status; @@ -359,7 +360,7 @@ AcpiGetObjectInfo ( { /* * Get extra info for ACPI Device/Processor objects only: - * Run the Device _HID, _UID, _SUB, and _CID methods. + * Run the Device _HID, _UID, _SUB, _CID, and _CLS methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used @@ -403,6 +404,15 @@ AcpiGetObjectInfo ( InfoSize += (CidList->ListSize - sizeof (ACPI_PNP_DEVICE_ID_LIST)); Valid |= ACPI_VALID_CID; } + + /* Execute the Device._CLS method */ + + Status = AcpiUtExecute_CLS (Node, &Cls); + if (ACPI_SUCCESS (Status)) + { + InfoSize += Cls->Length; + Valid |= ACPI_VALID_CLS; + } } /* @@ -534,6 +544,12 @@ AcpiGetObjectInfo ( } } + if (Cls) + { + NextIdString = AcpiNsCopyDeviceId (&Info->ClassCode, + Cls, NextIdString); + } + /* Copy the fixed-length data */ Info->InfoSize = InfoSize; @@ -563,6 +579,10 @@ Cleanup: { ACPI_FREE (CidList); } + if (Cls) + { + ACPI_FREE (Cls); + } return (Status); } @@ -684,7 +704,7 @@ AcpiInstallMethod ( /* Copy the method AML to the local buffer */ - ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength); + memcpy (AmlBuffer, AmlStart, AmlLength); /* Initialize the method object with the new method's information */ diff --git a/sys/contrib/dev/acpica/components/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c index 1a269a6..8581a94 100644 --- a/sys/contrib/dev/acpica/components/parser/psutils.c +++ b/sys/contrib/dev/acpica/components/parser/psutils.c @@ -104,7 +104,7 @@ AcpiPsInitOp ( Op->Common.DescriptorType = ACPI_DESC_TYPE_PARSER; Op->Common.AmlOpcode = Opcode; - ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (Op->Common.AmlOpName, + ACPI_DISASM_ONLY_MEMBERS (strncpy (Op->Common.AmlOpName, (AcpiPsGetOpcodeInfo (Opcode))->Name, sizeof (Op->Common.AmlOpName))); } diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c index c646129..6225590 100644 --- a/sys/contrib/dev/acpica/components/resources/rscreate.c +++ b/sys/contrib/dev/acpica/components/resources/rscreate.c @@ -374,12 +374,12 @@ AcpiRsCreatePciRoutingTable ( /* +1 to include null terminator */ - UserPrt->Length += (UINT32) ACPI_STRLEN (UserPrt->Source) + 1; + UserPrt->Length += (UINT32) strlen (UserPrt->Source) + 1; break; case ACPI_TYPE_STRING: - ACPI_STRCPY (UserPrt->Source, ObjDesc->String.Pointer); + strcpy (UserPrt->Source, ObjDesc->String.Pointer); /* * Add to the Length field the length of the string diff --git a/sys/contrib/dev/acpica/components/resources/rsmisc.c b/sys/contrib/dev/acpica/components/resources/rsmisc.c index bc5b803..cef8000 100644 --- a/sys/contrib/dev/acpica/components/resources/rsmisc.c +++ b/sys/contrib/dev/acpica/components/resources/rsmisc.c @@ -130,7 +130,7 @@ AcpiRsConvertAmlToResource ( /* * Get the resource type and the initial (minimum) length */ - ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info)); + memset (Resource, 0, INIT_RESOURCE_LENGTH (Info)); Resource->Type = INIT_RESOURCE_TYPE (Info); Resource->Length = INIT_RESOURCE_LENGTH (Info); break; @@ -326,13 +326,13 @@ AcpiRsConvertAmlToResource ( case ACPI_RSC_SET8: - ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value); + memset (Destination, Info->AmlOffset, Info->Value); break; case ACPI_RSC_DATA8: Target = ACPI_ADD_PTR (char, Resource, Info->Value); - ACPI_MEMCPY (Destination, Source, ACPI_GET16 (Target)); + memcpy (Destination, Source, ACPI_GET16 (Target)); break; case ACPI_RSC_ADDRESS: @@ -505,7 +505,7 @@ AcpiRsConvertResourceToAml ( { case ACPI_RSC_INITSET: - ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info)); + memset (Aml, 0, INIT_RESOURCE_LENGTH (Info)); AmlLength = INIT_RESOURCE_LENGTH (Info); AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml); break; diff --git a/sys/contrib/dev/acpica/components/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c index c0e7b78..1bab925 100644 --- a/sys/contrib/dev/acpica/components/resources/rsutils.c +++ b/sys/contrib/dev/acpica/components/resources/rsutils.c @@ -174,7 +174,7 @@ AcpiRsMoveData ( case ACPI_RSC_MOVE_SERIAL_VEN: case ACPI_RSC_MOVE_SERIAL_RES: - ACPI_MEMCPY (Destination, Source, ItemCount); + memcpy (Destination, Source, ItemCount); return; /* @@ -408,11 +408,11 @@ AcpiRsGetResourceSource ( * * Zero the entire area of the buffer. */ - TotalLength = (UINT32) ACPI_STRLEN ( + TotalLength = (UINT32) strlen ( ACPI_CAST_PTR (char, &AmlResourceSource[1])) + 1; TotalLength = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (TotalLength); - ACPI_MEMSET (ResourceSource->StringPtr, 0, TotalLength); + memset (ResourceSource->StringPtr, 0, TotalLength); /* Copy the ResourceSource string to the destination */ @@ -477,7 +477,7 @@ AcpiRsSetResourceSource ( /* Copy the ResourceSource string */ - ACPI_STRCPY (ACPI_CAST_PTR (char, &AmlResourceSource[1]), + strcpy (ACPI_CAST_PTR (char, &AmlResourceSource[1]), ResourceSource->StringPtr); /* diff --git a/sys/contrib/dev/acpica/components/resources/rsxface.c b/sys/contrib/dev/acpica/components/resources/rsxface.c index a477f20..66c26e1 100644 --- a/sys/contrib/dev/acpica/components/resources/rsxface.c +++ b/sys/contrib/dev/acpica/components/resources/rsxface.c @@ -447,7 +447,7 @@ AcpiResourceToAddress64 ( /* Simple copy for 64 bit source */ - ACPI_MEMCPY (Out, &Resource->Data, sizeof (ACPI_RESOURCE_ADDRESS64)); + memcpy (Out, &Resource->Data, sizeof (ACPI_RESOURCE_ADDRESS64)); break; default: @@ -558,7 +558,7 @@ AcpiRsMatchVendorResource ( */ if ((Vendor->ByteLength < (ACPI_UUID_LENGTH + 1)) || (Vendor->UuidSubtype != Info->Uuid->Subtype) || - (ACPI_MEMCMP (Vendor->Uuid, Info->Uuid->Data, ACPI_UUID_LENGTH))) + (memcmp (Vendor->Uuid, Info->Uuid->Data, ACPI_UUID_LENGTH))) { return (AE_OK); } @@ -574,7 +574,7 @@ AcpiRsMatchVendorResource ( /* Found the correct resource, copy and return it */ - ACPI_MEMCPY (Buffer->Pointer, Resource, Resource->Length); + memcpy (Buffer->Pointer, Resource, Resource->Length); Buffer->Length = Resource->Length; /* Found the desired descriptor, terminate resource walk */ diff --git a/sys/contrib/dev/acpica/components/tables/tbdata.c b/sys/contrib/dev/acpica/components/tables/tbdata.c index 70bac2c..b44dec0 100644 --- a/sys/contrib/dev/acpica/components/tables/tbdata.c +++ b/sys/contrib/dev/acpica/components/tables/tbdata.c @@ -77,7 +77,7 @@ AcpiTbInitTableDescriptor ( * Initialize the table descriptor. Set the pointer to NULL, since the * table is not fully mapped at this time. */ - ACPI_MEMSET (TableDesc, 0, sizeof (ACPI_TABLE_DESC)); + memset (TableDesc, 0, sizeof (ACPI_TABLE_DESC)); TableDesc->Address = Address; TableDesc->Length = Table->Length; TableDesc->Flags = Flags; @@ -511,7 +511,7 @@ AcpiTbResizeRootTableList ( if (AcpiGbl_RootTableList.Tables) { - ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, + memcpy (Tables, AcpiGbl_RootTableList.Tables, (ACPI_SIZE) TableCount * sizeof (ACPI_TABLE_DESC)); if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) diff --git a/sys/contrib/dev/acpica/components/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c index f35e217..0917157 100644 --- a/sys/contrib/dev/acpica/components/tables/tbfadt.c +++ b/sys/contrib/dev/acpica/components/tables/tbfadt.c @@ -382,8 +382,16 @@ AcpiTbParseFadt ( if (!AcpiGbl_ReducedHardware) { - AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, - ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + if (AcpiGbl_FADT.Facs) + { + AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.Facs, + ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + } + if (AcpiGbl_FADT.XFacs) + { + AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, + ACPI_SIG_FACS, ACPI_TABLE_INDEX_X_FACS); + } } } @@ -425,11 +433,11 @@ AcpiTbCreateLocalFadt ( /* Clear the entire local FADT */ - ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); + memset (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */ - ACPI_MEMCPY (&AcpiGbl_FADT, Table, + memcpy (&AcpiGbl_FADT, Table, ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT))); /* Take a copy of the Hardware Reduced flag */ @@ -533,12 +541,9 @@ AcpiTbConvertFadt ( AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); /* - * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Expand the 32-bit DSDT addresses to 64-bit as necessary. * Later ACPICA code will always use the X 64-bit field. */ - AcpiGbl_FADT.XFacs = AcpiTbSelectAddress ("FACS", - AcpiGbl_FADT.Facs, AcpiGbl_FADT.XFacs); - AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT", AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt); diff --git a/sys/contrib/dev/acpica/components/tables/tbfind.c b/sys/contrib/dev/acpica/components/tables/tbfind.c index 30a5750..e5c4cee 100644 --- a/sys/contrib/dev/acpica/components/tables/tbfind.c +++ b/sys/contrib/dev/acpica/components/tables/tbfind.c @@ -83,16 +83,16 @@ AcpiTbFindTable ( /* Normalize the input strings */ - ACPI_MEMSET (&Header, 0, sizeof (ACPI_TABLE_HEADER)); + memset (&Header, 0, sizeof (ACPI_TABLE_HEADER)); ACPI_MOVE_NAME (Header.Signature, Signature); - ACPI_STRNCPY (Header.OemId, OemId, ACPI_OEM_ID_SIZE); - ACPI_STRNCPY (Header.OemTableId, OemTableId, ACPI_OEM_TABLE_ID_SIZE); + strncpy (Header.OemId, OemId, ACPI_OEM_ID_SIZE); + strncpy (Header.OemTableId, OemTableId, ACPI_OEM_TABLE_ID_SIZE); /* Search for the table */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { - if (ACPI_MEMCMP (&(AcpiGbl_RootTableList.Tables[i].Signature), + if (memcmp (&(AcpiGbl_RootTableList.Tables[i].Signature), Header.Signature, ACPI_NAME_SIZE)) { /* Not the requested table */ @@ -120,13 +120,13 @@ AcpiTbFindTable ( /* Check for table match on all IDs */ - if (!ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->Signature, + if (!memcmp (AcpiGbl_RootTableList.Tables[i].Pointer->Signature, Header.Signature, ACPI_NAME_SIZE) && (!OemId[0] || - !ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->OemId, + !memcmp (AcpiGbl_RootTableList.Tables[i].Pointer->OemId, Header.OemId, ACPI_OEM_ID_SIZE)) && (!OemTableId[0] || - !ACPI_MEMCMP (AcpiGbl_RootTableList.Tables[i].Pointer->OemTableId, + !memcmp (AcpiGbl_RootTableList.Tables[i].Pointer->OemTableId, Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE))) { *TableIndex = i; diff --git a/sys/contrib/dev/acpica/components/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c index d77d2c8..a6680cf 100644 --- a/sys/contrib/dev/acpica/components/tables/tbinstal.c +++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c @@ -94,7 +94,7 @@ AcpiTbCompareTables ( * not just the header. */ IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength || - ACPI_MEMCMP (TableDesc->Pointer, Table, TableLength)) ? + memcmp (TableDesc->Pointer, Table, TableLength)) ? FALSE : TRUE); /* Release the acquired table */ @@ -309,7 +309,7 @@ AcpiTbInstallStandardTable ( */ if ((NewTableDesc.Signature.Ascii[0] != 0x00) && (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) && - (ACPI_STRNCMP (NewTableDesc.Signature.Ascii, "OEM", 3))) + (strncmp (NewTableDesc.Signature.Ascii, "OEM", 3))) { ACPI_BIOS_ERROR ((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " diff --git a/sys/contrib/dev/acpica/components/tables/tbprint.c b/sys/contrib/dev/acpica/components/tables/tbprint.c index f0ea090..f56d002 100644 --- a/sys/contrib/dev/acpica/components/tables/tbprint.c +++ b/sys/contrib/dev/acpica/components/tables/tbprint.c @@ -84,7 +84,7 @@ AcpiTbFixString ( while (Length && *String) { - if (!ACPI_IS_PRINT (*String)) + if (!isprint ((int) *String)) { *String = '?'; } @@ -114,7 +114,7 @@ AcpiTbCleanupTableHeader ( ACPI_TABLE_HEADER *Header) { - ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); + memcpy (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE); AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); @@ -156,7 +156,7 @@ AcpiTbPrintTableHeader ( { /* RSDP has no common fields */ - ACPI_MEMCPY (LocalHeader.OemId, + memcpy (LocalHeader.OemId, ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE); AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); diff --git a/sys/contrib/dev/acpica/components/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c index 8b80025..94ac4f9 100644 --- a/sys/contrib/dev/acpica/components/tables/tbutils.c +++ b/sys/contrib/dev/acpica/components/tables/tbutils.c @@ -75,8 +75,6 @@ ACPI_STATUS AcpiTbInitializeFacs ( void) { - ACPI_STATUS Status; - /* If Hardware Reduced flag is set, there is no FACS */ @@ -86,9 +84,23 @@ AcpiTbInitializeFacs ( return (AE_OK); } - Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, - ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); - return (Status); + (void) AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_Facs32)); + (void) AcpiGetTableByIndex (ACPI_TABLE_INDEX_X_FACS, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_Facs64)); + + if (AcpiGbl_Facs64 && (!AcpiGbl_Facs32 || !AcpiGbl_Use32BitFacsAddresses)) + { + AcpiGbl_FACS = AcpiGbl_Facs64; + } + else if (AcpiGbl_Facs32) + { + AcpiGbl_FACS = AcpiGbl_Facs32; + } + + /* If there is no FACS, just continue. There was already an error msg */ + + return (AE_OK); } #endif /* !ACPI_REDUCED_HARDWARE */ @@ -111,7 +123,7 @@ AcpiTbTablesLoaded ( void) { - if (AcpiGbl_RootTableList.CurrentTableCount >= 3) + if (AcpiGbl_RootTableList.CurrentTableCount >= 4) { return (TRUE); } @@ -190,7 +202,7 @@ AcpiTbCopyDsdt ( return (NULL); } - ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); + memcpy (NewTable, TableDesc->Pointer, TableDesc->Length); AcpiTbUninstallTable (TableDesc); AcpiTbInitTableDescriptor ( @@ -389,11 +401,11 @@ AcpiTbParseRootTable ( TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER)); /* - * First two entries in the table array are reserved for the DSDT - * and FACS, which are not actually present in the RSDT/XSDT - they - * come from the FADT + * First three entries in the table array are reserved for the DSDT + * and 32bit/64bit FACS, which are not actually present in the + * RSDT/XSDT - they come from the FADT */ - AcpiGbl_RootTableList.CurrentTableCount = 2; + AcpiGbl_RootTableList.CurrentTableCount = 3; /* Initialize the root table array from the RSDT/XSDT */ diff --git a/sys/contrib/dev/acpica/components/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c index 7336b18..67f6fea 100644 --- a/sys/contrib/dev/acpica/components/tables/tbxface.c +++ b/sys/contrib/dev/acpica/components/tables/tbxface.c @@ -132,7 +132,7 @@ AcpiInitializeTables ( { /* Root Table Array has been statically allocated by the host */ - ACPI_MEMSET (InitialTableArray, 0, + memset (InitialTableArray, 0, (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC)); AcpiGbl_RootTableList.Tables = InitialTableArray; @@ -271,7 +271,7 @@ AcpiGetTableHeader ( return (AE_NO_MEMORY); } - ACPI_MEMCPY (OutTableHeader, Header, + memcpy (OutTableHeader, Header, sizeof (ACPI_TABLE_HEADER)); AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER)); } @@ -282,7 +282,7 @@ AcpiGetTableHeader ( } else { - ACPI_MEMCPY (OutTableHeader, + memcpy (OutTableHeader, AcpiGbl_RootTableList.Tables[i].Pointer, sizeof (ACPI_TABLE_HEADER)); } diff --git a/sys/contrib/dev/acpica/components/tables/tbxfload.c b/sys/contrib/dev/acpica/components/tables/tbxfload.c index 805bbad..014d68b 100644 --- a/sys/contrib/dev/acpica/components/tables/tbxfload.c +++ b/sys/contrib/dev/acpica/components/tables/tbxfload.c @@ -164,7 +164,7 @@ AcpiTbLoadNamespace ( * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ - ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, + memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, sizeof (ACPI_TABLE_HEADER)); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); @@ -182,10 +182,13 @@ AcpiTbLoadNamespace ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { - if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + if (!AcpiGbl_RootTableList.Tables[i].Address || + (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), ACPI_SIG_SSDT) && !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), - ACPI_SIG_PSDT)) || + ACPI_SIG_PSDT) && + !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), + ACPI_SIG_OSDT)) || ACPI_FAILURE (AcpiTbValidateTable ( &AcpiGbl_RootTableList.Tables[i]))) { @@ -238,11 +241,11 @@ AcpiInstallTable ( if (Physical) { - Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; + Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; } else { - Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; + Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; } Status = AcpiTbInstallStandardTable (Address, Flags, diff --git a/sys/contrib/dev/acpica/components/utilities/utalloc.c b/sys/contrib/dev/acpica/components/utilities/utalloc.c index 99fb15a1..c26259d 100644 --- a/sys/contrib/dev/acpica/components/utilities/utalloc.c +++ b/sys/contrib/dev/acpica/components/utilities/utalloc.c @@ -79,7 +79,7 @@ AcpiOsAllocateZeroed ( { /* Clear the memory block */ - ACPI_MEMSET (Allocation, 0, Size); + memset (Allocation, 0, Size); } return (Allocation); @@ -189,7 +189,7 @@ AcpiUtDeleteCaches ( if (AcpiGbl_DisplayFinalMemStats) { - ACPI_STRCPY (Buffer, "MEMORY"); + strcpy (Buffer, "MEMORY"); (void) AcpiDbDisplayStatistics (Buffer); } #endif @@ -359,6 +359,6 @@ AcpiUtInitializeBuffer ( /* Have a valid buffer, clear it */ - ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength); + memset (Buffer->Pointer, 0, RequiredLength); return (AE_OK); } diff --git a/sys/contrib/dev/acpica/components/utilities/utbuffer.c b/sys/contrib/dev/acpica/components/utilities/utbuffer.c index cc41419..08a42cd 100644 --- a/sys/contrib/dev/acpica/components/utilities/utbuffer.c +++ b/sys/contrib/dev/acpica/components/utilities/utbuffer.c @@ -168,7 +168,7 @@ AcpiUtDumpBuffer ( } BufChar = Buffer[(ACPI_SIZE) i + j]; - if (ACPI_IS_PRINT (BufChar)) + if (isprint (BufChar)) { AcpiOsPrintf ("%c", BufChar); } @@ -341,7 +341,7 @@ AcpiUtDumpBufferToFile ( } BufChar = Buffer[(ACPI_SIZE) i + j]; - if (ACPI_IS_PRINT (BufChar)) + if (isprint (BufChar)) { AcpiUtFilePrintf (File, "%c", BufChar); } diff --git a/sys/contrib/dev/acpica/components/utilities/utcache.c b/sys/contrib/dev/acpica/components/utilities/utcache.c index aa0161c..c252d8a 100644 --- a/sys/contrib/dev/acpica/components/utilities/utcache.c +++ b/sys/contrib/dev/acpica/components/utilities/utcache.c @@ -92,7 +92,7 @@ AcpiOsCreateCache ( /* Populate the cache object and return it */ - ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); Cache->ListName = CacheName; Cache->ObjectSize = ObjectSize; Cache->MaxDepth = MaxDepth; @@ -242,7 +242,7 @@ AcpiOsReleaseObject ( /* Mark the object as cached */ - ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize); + memset (Object, 0xCA, Cache->ObjectSize); ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); /* Put the object at the head of the cache list */ @@ -318,7 +318,7 @@ AcpiOsAcquireObject ( /* Clear (zero) the previously used Object */ - ACPI_MEMSET (Object, 0, Cache->ObjectSize); + memset (Object, 0, Cache->ObjectSize); } else { diff --git a/sys/contrib/dev/acpica/components/utilities/utcopy.c b/sys/contrib/dev/acpica/components/utilities/utcopy.c index 8a94ea6..2032dd4 100644 --- a/sys/contrib/dev/acpica/components/utilities/utcopy.c +++ b/sys/contrib/dev/acpica/components/utilities/utcopy.c @@ -146,7 +146,7 @@ AcpiUtCopyIsimpleToEsimple ( /* Always clear the external object */ - ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT)); + memset (ExternalObject, 0, sizeof (ACPI_OBJECT)); /* * In general, the external object will be the same type as @@ -165,7 +165,7 @@ AcpiUtCopyIsimpleToEsimple ( *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( (ACPI_SIZE) InternalObject->String.Length + 1); - ACPI_MEMCPY ((void *) DataSpace, + memcpy ((void *) DataSpace, (void *) InternalObject->String.Pointer, (ACPI_SIZE) InternalObject->String.Length + 1); break; @@ -177,7 +177,7 @@ AcpiUtCopyIsimpleToEsimple ( *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( InternalObject->String.Length); - ACPI_MEMCPY ((void *) DataSpace, + memcpy ((void *) DataSpace, (void *) InternalObject->Buffer.Pointer, InternalObject->Buffer.Length); break; @@ -528,7 +528,7 @@ AcpiUtCopyEsimpleToIsimple ( goto ErrorExit; } - ACPI_MEMCPY (InternalObject->String.Pointer, + memcpy (InternalObject->String.Pointer, ExternalObject->String.Pointer, ExternalObject->String.Length); @@ -544,7 +544,7 @@ AcpiUtCopyEsimpleToIsimple ( goto ErrorExit; } - ACPI_MEMCPY (InternalObject->Buffer.Pointer, + memcpy (InternalObject->Buffer.Pointer, ExternalObject->Buffer.Pointer, ExternalObject->Buffer.Length); @@ -732,7 +732,7 @@ AcpiUtCopySimpleObject ( CopySize = sizeof (ACPI_NAMESPACE_NODE); } - ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc), + memcpy (ACPI_CAST_PTR (char, DestDesc), ACPI_CAST_PTR (char, SourceDesc), CopySize); /* Restore the saved fields */ @@ -766,7 +766,7 @@ AcpiUtCopySimpleObject ( /* Copy the actual buffer data */ - ACPI_MEMCPY (DestDesc->Buffer.Pointer, + memcpy (DestDesc->Buffer.Pointer, SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); } break; @@ -788,7 +788,7 @@ AcpiUtCopySimpleObject ( /* Copy the actual string data */ - ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, + memcpy (DestDesc->String.Pointer, SourceDesc->String.Pointer, (ACPI_SIZE) SourceDesc->String.Length + 1); } break; diff --git a/sys/contrib/dev/acpica/components/utilities/utids.c b/sys/contrib/dev/acpica/components/utilities/utids.c index 7d31429..6378e26 100644 --- a/sys/contrib/dev/acpica/components/utilities/utids.c +++ b/sys/contrib/dev/acpica/components/utilities/utids.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: utids - support for device IDs - HID, UID, CID + * Module Name: utids - support for device IDs - HID, UID, CID, SUB, CLS * *****************************************************************************/ @@ -121,7 +121,7 @@ AcpiUtExecute_HID ( } else { - ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer); + strcpy (Hid->String, ObjDesc->String.Pointer); } Hid->Length = Length; @@ -194,7 +194,7 @@ AcpiUtExecute_SUB ( /* Simply copy existing string */ - ACPI_STRCPY (Sub->String, ObjDesc->String.Pointer); + strcpy (Sub->String, ObjDesc->String.Pointer); Sub->Length = Length; *ReturnId = Sub; @@ -279,7 +279,7 @@ AcpiUtExecute_UID ( } else { - ACPI_STRCPY (Uid->String, ObjDesc->String.Pointer); + strcpy (Uid->String, ObjDesc->String.Pointer); } Uid->Length = Length; @@ -426,7 +426,7 @@ AcpiUtExecute_CID ( { /* Copy the String CID from the returned object */ - ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer); + strcpy (NextIdString, CidObjects[i]->String.Pointer); Length = CidObjects[i]->String.Length + 1; } @@ -449,3 +449,97 @@ Cleanup: AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_CLS + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the _CLS is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _CLS control method that returns PCI-defined + * class code of the device. The _CLS value is always a package + * containing PCI class information as a list of integers. + * The returned string has format "BBSSPP", where: + * BB = Base-class code + * SS = Sub-class code + * PP = Programming Interface code + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_CLS ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT **ClsObjects; + UINT32 Count; + ACPI_PNP_DEVICE_ID *Cls; + UINT32 Length; + ACPI_STATUS Status; + UINT8 ClassCode[3] = {0, 0, 0}; + + + ACPI_FUNCTION_TRACE (UtExecute_CLS); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CLS, + ACPI_BTYPE_PACKAGE, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + Length = ACPI_PCICLS_STRING_SIZE; + ClsObjects = ObjDesc->Package.Elements; + Count = ObjDesc->Package.Count; + + if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + if (Count > 0 && ClsObjects[0]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[0] = (UINT8) ClsObjects[0]->Integer.Value; + } + if (Count > 1 && ClsObjects[1]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[1] = (UINT8) ClsObjects[1]->Integer.Value; + } + if (Count > 2 && ClsObjects[2]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[2] = (UINT8) ClsObjects[2]->Integer.Value; + } + } + + /* Allocate a buffer for the CLS */ + + Cls = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Cls) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + Cls->String = ACPI_ADD_PTR (char, Cls, sizeof (ACPI_PNP_DEVICE_ID)); + + /* Simply copy existing string */ + + AcpiExPciClsToString (Cls->String, ClassCode); + Cls->Length = Length; + *ReturnId = Cls; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c index f3d2222..1aa02b8 100644 --- a/sys/contrib/dev/acpica/components/utilities/utmisc.c +++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c @@ -71,10 +71,10 @@ AcpiUtIsPciRootBridge ( * Check if this is a PCI root bridge. * ACPI 3.0+: check for a PCI Express root also. */ - if (!(ACPI_STRCMP (Id, + if (!(strcmp (Id, PCI_ROOT_HID_STRING)) || - !(ACPI_STRCMP (Id, + !(strcmp (Id, PCI_EXPRESS_ROOT_HID_STRING))) { return (TRUE); @@ -108,7 +108,8 @@ AcpiUtIsAmlTable ( if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_PSDT) || - ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT)) + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) || + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_OSDT)) { return (TRUE); } diff --git a/sys/contrib/dev/acpica/components/utilities/utosi.c b/sys/contrib/dev/acpica/components/utilities/utosi.c index bf6ba86..d0dd1dc 100644 --- a/sys/contrib/dev/acpica/components/utilities/utosi.c +++ b/sys/contrib/dev/acpica/components/utilities/utosi.c @@ -256,7 +256,7 @@ AcpiUtInstallInterface ( return (AE_NO_MEMORY); } - InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1); + InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (strlen (InterfaceName) + 1); if (!InterfaceInfo->Name) { ACPI_FREE (InterfaceInfo); @@ -265,7 +265,7 @@ AcpiUtInstallInterface ( /* Initialize new info and insert at the head of the global list */ - ACPI_STRCPY (InterfaceInfo->Name, InterfaceName); + strcpy (InterfaceInfo->Name, InterfaceName); InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; @@ -298,7 +298,7 @@ AcpiUtRemoveInterface ( PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; while (NextInterface) { - if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + if (!strcmp (InterfaceName, NextInterface->Name)) { /* Found: name is in either the static list or was added at runtime */ @@ -419,7 +419,7 @@ AcpiUtGetInterface ( NextInterface = AcpiGbl_SupportedInterfaces; while (NextInterface) { - if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + if (!strcmp (InterfaceName, NextInterface->Name)) { return (NextInterface); } diff --git a/sys/contrib/dev/acpica/components/utilities/utpredef.c b/sys/contrib/dev/acpica/components/utilities/utpredef.c index a445f85..fed8154 100644 --- a/sys/contrib/dev/acpica/components/utilities/utpredef.c +++ b/sys/contrib/dev/acpica/components/utilities/utpredef.c @@ -166,7 +166,7 @@ AcpiUtGetExpectedReturnTypes ( if (!ExpectedBtypes) { - ACPI_STRCPY (Buffer, "NONE"); + strcpy (Buffer, "NONE"); return; } @@ -180,7 +180,7 @@ AcpiUtGetExpectedReturnTypes ( if (ExpectedBtypes & ThisRtype) { - ACPI_STRCAT (Buffer, &UtRtypeNames[i][j]); + strcat (Buffer, &UtRtypeNames[i][j]); j = 0; /* Use name separator from now on */ } diff --git a/sys/contrib/dev/acpica/components/utilities/utprint.c b/sys/contrib/dev/acpica/components/utilities/utprint.c index 62aecf0..dee3a71 100644 --- a/sys/contrib/dev/acpica/components/utilities/utprint.c +++ b/sys/contrib/dev/acpica/components/utilities/utprint.c @@ -227,7 +227,7 @@ AcpiUtScanNumber ( UINT64 Number = 0; - while (ACPI_IS_DIGIT (*String)) + while (isdigit ((int) *String)) { Number *= 10; Number += *(String++) - '0'; @@ -505,7 +505,7 @@ AcpiUtVsnprintf ( /* Process width */ Width = -1; - if (ACPI_IS_DIGIT (*Format)) + if (isdigit ((int) *Format)) { Format = AcpiUtScanNumber (Format, &Number); Width = (INT32) Number; @@ -527,7 +527,7 @@ AcpiUtVsnprintf ( if (*Format == '.') { ++Format; - if (ACPI_IS_DIGIT(*Format)) + if (isdigit ((int) *Format)) { Format = AcpiUtScanNumber (Format, &Number); Precision = (INT32) Number; diff --git a/sys/contrib/dev/acpica/components/utilities/utstring.c b/sys/contrib/dev/acpica/components/utilities/utstring.c index 4cbf435..6d38a5b 100644 --- a/sys/contrib/dev/acpica/components/utilities/utstring.c +++ b/sys/contrib/dev/acpica/components/utilities/utstring.c @@ -89,7 +89,7 @@ AcpiUtStrlwr ( for (String = SrcString; *String; String++) { - *String = (char) ACPI_TOLOWER (*String); + *String = (char) tolower ((int) *String); } return; @@ -168,7 +168,7 @@ AcpiUtStrupr ( for (String = SrcString; *String; String++) { - *String = (char) ACPI_TOUPPER (*String); + *String = (char) toupper ((int) *String); } return; @@ -234,7 +234,7 @@ AcpiUtStrtoul64 ( /* Skip over any white space in the buffer */ - while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t')) + while ((*String) && (isspace ((int) *String) || *String == '\t')) { String++; } @@ -245,7 +245,7 @@ AcpiUtStrtoul64 ( * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. * We need to determine if it is decimal or hexadecimal. */ - if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x')) + if ((*String == '0') && (tolower ((int) *(String + 1)) == 'x')) { SignOf0x = 1; Base = 16; @@ -261,7 +261,7 @@ AcpiUtStrtoul64 ( /* Any string left? Check that '0x' is not followed by white space. */ - if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t') + if (!(*String) || isspace ((int) *String) || *String == '\t') { if (ToIntegerOp) { @@ -283,7 +283,7 @@ AcpiUtStrtoul64 ( while (*String) { - if (ACPI_IS_DIGIT (*String)) + if (isdigit ((int) *String)) { /* Convert ASCII 0-9 to Decimal value */ @@ -297,8 +297,8 @@ AcpiUtStrtoul64 ( } else { - ThisDigit = (UINT8) ACPI_TOUPPER (*String); - if (ACPI_IS_XDIGIT ((char) ThisDigit)) + ThisDigit = (UINT8) toupper ((int) *String); + if (isxdigit ((int) ThisDigit)) { /* Convert ASCII Hex char to value */ @@ -469,7 +469,7 @@ AcpiUtPrintString ( /* Check for printable character or hex escape */ - if (ACPI_IS_PRINT (String[i])) + if (isprint ((int) String[i])) { /* This is a normal character */ @@ -711,12 +711,12 @@ AcpiUtSafeStrcpy ( char *Source) { - if (ACPI_STRLEN (Source) >= DestSize) + if (strlen (Source) >= DestSize) { return (TRUE); } - ACPI_STRCPY (Dest, Source); + strcpy (Dest, Source); return (FALSE); } @@ -727,12 +727,12 @@ AcpiUtSafeStrcat ( char *Source) { - if ((ACPI_STRLEN (Dest) + ACPI_STRLEN (Source)) >= DestSize) + if ((strlen (Dest) + strlen (Source)) >= DestSize) { return (TRUE); } - ACPI_STRCAT (Dest, Source); + strcat (Dest, Source); return (FALSE); } @@ -747,14 +747,14 @@ AcpiUtSafeStrncat ( ACPI_SIZE ActualTransferLength; - ActualTransferLength = ACPI_MIN (MaxTransferLength, ACPI_STRLEN (Source)); + ActualTransferLength = ACPI_MIN (MaxTransferLength, strlen (Source)); - if ((ACPI_STRLEN (Dest) + ActualTransferLength) >= DestSize) + if ((strlen (Dest) + ActualTransferLength) >= DestSize) { return (TRUE); } - ACPI_STRNCAT (Dest, Source, MaxTransferLength); + strncat (Dest, Source, MaxTransferLength); return (FALSE); } #endif diff --git a/sys/contrib/dev/acpica/components/utilities/uttrack.c b/sys/contrib/dev/acpica/components/utilities/uttrack.c index 5f208b5..d780397 100644 --- a/sys/contrib/dev/acpica/components/utilities/uttrack.c +++ b/sys/contrib/dev/acpica/components/utilities/uttrack.c @@ -113,7 +113,7 @@ AcpiUtCreateList ( return (AE_NO_MEMORY); } - ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); Cache->ListName = ListName; Cache->ObjectSize = ObjectSize; @@ -445,7 +445,7 @@ AcpiUtTrackAllocation ( Allocation->Component = Component; Allocation->Line = Line; - ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); + strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; if (!Element) @@ -556,7 +556,7 @@ AcpiUtRemoveAllocation ( /* Mark the segment as deleted */ - ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size); + memset (&Allocation->UserSpace, 0xEA, Allocation->Size); Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); return (Status); @@ -667,7 +667,7 @@ AcpiUtDumpAllocations ( while (Element) { if ((Element->Component & Component) && - ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) + ((Module == NULL) || (0 == strcmp (Module, Element->Module)))) { Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); diff --git a/sys/contrib/dev/acpica/components/utilities/utxface.c b/sys/contrib/dev/acpica/components/utilities/utxface.c index aab7473..eb311ec 100644 --- a/sys/contrib/dev/acpica/components/utilities/utxface.c +++ b/sys/contrib/dev/acpica/components/utilities/utxface.c @@ -263,7 +263,7 @@ AcpiGetStatistics ( Stats->SciCount = AcpiSciCount; Stats->GpeCount = AcpiGpeCount; - ACPI_MEMCPY (Stats->FixedEventCount, AcpiFixedEventCount, + memcpy (Stats->FixedEventCount, AcpiFixedEventCount, sizeof (AcpiFixedEventCount)); @@ -367,7 +367,7 @@ AcpiInstallInterface ( /* Parameter validation */ - if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + if (!InterfaceName || (strlen (InterfaceName) == 0)) { return (AE_BAD_PARAMETER); } @@ -432,7 +432,7 @@ AcpiRemoveInterface ( /* Parameter validation */ - if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + if (!InterfaceName || (strlen (InterfaceName) == 0)) { return (AE_BAD_PARAMETER); } diff --git a/sys/contrib/dev/acpica/components/utilities/utxfinit.c b/sys/contrib/dev/acpica/components/utilities/utxfinit.c index 36107ca..04cd24f 100644 --- a/sys/contrib/dev/acpica/components/utilities/utxfinit.c +++ b/sys/contrib/dev/acpica/components/utilities/utxfinit.c @@ -194,11 +194,14 @@ AcpiEnableSubsystem ( * Obtain a permanent mapping for the FACS. This is required for the * Global Lock and the Firmware Waking Vector */ - Status = AcpiTbInitializeFacs (); - if (ACPI_FAILURE (Status)) + if (!(Flags & ACPI_NO_FACS_INIT)) { - ACPI_WARNING ((AE_INFO, "Could not map the FACS table")); - return_ACPI_STATUS (Status); + Status = AcpiTbInitializeFacs (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS (Status); + } } #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/include/acclib.h b/sys/contrib/dev/acpica/include/acclib.h new file mode 100644 index 0000000..ed310cc --- /dev/null +++ b/sys/contrib/dev/acpica/include/acclib.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * + * Name: acclib.h -- C library support. Prototypes for the (optional) local + * implementations of required C library functions. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, Intel Corp. + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#ifndef _ACCLIB_H +#define _ACCLIB_H + + +/* + * Prototypes and macros for local implementations of C library functions + */ + +/* is* functions. The AcpiGbl_Ctypes array is defined in utclib.c */ + +extern const UINT8 AcpiGbl_Ctypes[]; + +#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ +#define _ACPI_XS 0x40 /* extra space */ +#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ +#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ +#define _ACPI_DI 0x04 /* '0'-'9' */ +#define _ACPI_LO 0x02 /* 'a'-'z' */ +#define _ACPI_PU 0x10 /* punctuation */ +#define _ACPI_SP 0x08 /* space, tab, CR, LF, VT, FF */ +#define _ACPI_UP 0x01 /* 'A'-'Z' */ +#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ + +#define isdigit(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_DI)) +#define isspace(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_SP)) +#define isxdigit(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_XD)) +#define isupper(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_UP)) +#define islower(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO)) +#define isprint(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) +#define isalpha(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) + + +/* Strings */ + +char * +strcat ( + char *DstString, + const char *SrcString); + +char * +strchr ( + const char *String, + int ch); + +char * +strcpy ( + char *DstString, + const char *SrcString); + +int +strcmp ( + const char *String1, + const char *String2); + +ACPI_SIZE +strlen ( + const char *String); + +char * +strncat ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +int +strncmp ( + const char *String1, + const char *String2, + ACPI_SIZE Count); + +char * +strncpy ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +char * +strstr ( + char *String1, + char *String2); + + +/* Conversion */ + +UINT32 +strtoul ( + const char *String, + char **Terminator, + UINT32 Base); + + +/* Memory */ + +int +memcmp ( + void *Buffer1, + void *Buffer2, + ACPI_SIZE Count); + +void * +memcpy ( + void *Dest, + const void *Src, + ACPI_SIZE Count); + +void * +memset ( + void *Dest, + int Value, + ACPI_SIZE Count); + + +/* upper/lower case */ + +int +tolower ( + int c); + +int +toupper ( + int c); + +#endif /* _ACCLIB_H */ diff --git a/sys/contrib/dev/acpica/include/accommon.h b/sys/contrib/dev/acpica/include/accommon.h index e63943b..322222a 100644 --- a/sys/contrib/dev/acpica/include/accommon.h +++ b/sys/contrib/dev/acpica/include/accommon.h @@ -59,6 +59,9 @@ #include <contrib/dev/acpica/include/acglobal.h> /* All global variables */ #include <contrib/dev/acpica/include/achware.h> /* Hardware defines and interfaces */ #include <contrib/dev/acpica/include/acutils.h> /* Utility interfaces */ +#ifndef ACPI_USE_SYSTEM_CLIBRARY +#include <contrib/dev/acpica/include/acclib.h> /* C library interfaces */ +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ #endif /* __ACCOMMON_H__ */ diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h index ab2fc26..9e7da94 100644 --- a/sys/contrib/dev/acpica/include/acglobal.h +++ b/sys/contrib/dev/acpica/include/acglobal.h @@ -62,6 +62,8 @@ ACPI_GLOBAL (ACPI_TABLE_HEADER, AcpiGbl_OriginalDsdtHeader); #if (!ACPI_REDUCED_HARDWARE) ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_FACS); +ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_Facs32); +ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_Facs64); #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h index 66463d6..00eb8f0 100644 --- a/sys/contrib/dev/acpica/include/acinterp.h +++ b/sys/contrib/dev/acpica/include/acinterp.h @@ -638,6 +638,11 @@ AcpiExIntegerToString ( char *Dest, UINT64 Value); +void +AcpiExPciClsToString ( + char *Dest, + UINT8 ClassCode[3]); + BOOLEAN AcpiIsValidSpaceId ( UINT8 SpaceId); diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h index 4c96303..dc1afff 100644 --- a/sys/contrib/dev/acpica/include/aclocal.h +++ b/sys/contrib/dev/acpica/include/aclocal.h @@ -238,6 +238,7 @@ typedef struct acpi_table_list #define ACPI_TABLE_INDEX_DSDT (0) #define ACPI_TABLE_INDEX_FACS (1) +#define ACPI_TABLE_INDEX_X_FACS (2) typedef struct acpi_find_context diff --git a/sys/contrib/dev/acpica/include/acnames.h b/sys/contrib/dev/acpica/include/acnames.h index 6bb6bbf..6887d42 100644 --- a/sys/contrib/dev/acpica/include/acnames.h +++ b/sys/contrib/dev/acpica/include/acnames.h @@ -51,6 +51,7 @@ #define METHOD_NAME__BBN "_BBN" #define METHOD_NAME__CBA "_CBA" #define METHOD_NAME__CID "_CID" +#define METHOD_NAME__CLS "_CLS" #define METHOD_NAME__CRS "_CRS" #define METHOD_NAME__DDN "_DDN" #define METHOD_NAME__HID "_HID" diff --git a/sys/contrib/dev/acpica/include/acnamesp.h b/sys/contrib/dev/acpica/include/acnamesp.h index 07e76b5..786fd29 100644 --- a/sys/contrib/dev/acpica/include/acnamesp.h +++ b/sys/contrib/dev/acpica/include/acnamesp.h @@ -67,6 +67,7 @@ #define ACPI_NS_PREFIX_IS_SCOPE 0x10 #define ACPI_NS_EXTERNAL 0x20 #define ACPI_NS_TEMPORARY 0x40 +#define ACPI_NS_OVERRIDE_IF_FOUND 0x80 /* Flags for AcpiNsWalkNamespace */ diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h index b7b624b..481eb44 100644 --- a/sys/contrib/dev/acpica/include/acobject.h +++ b/sys/contrib/dev/acpica/include/acobject.h @@ -430,13 +430,14 @@ typedef struct acpi_object_addr_handler typedef struct acpi_object_reference { ACPI_OBJECT_COMMON_HEADER - UINT8 Class; /* Reference Class */ - UINT8 TargetType; /* Used for Index Op */ - UINT8 Reserved; - void *Object; /* NameOp=>HANDLE to obj, IndexOp=>ACPI_OPERAND_OBJECT */ - ACPI_NAMESPACE_NODE *Node; /* RefOf or Namepath */ - union acpi_operand_object **Where; /* Target of Index */ - UINT32 Value; /* Used for Local/Arg/Index/DdbHandle */ + UINT8 Class; /* Reference Class */ + UINT8 TargetType; /* Used for Index Op */ + UINT8 Reserved; + void *Object; /* NameOp=>HANDLE to obj, IndexOp=>ACPI_OPERAND_OBJECT */ + ACPI_NAMESPACE_NODE *Node; /* RefOf or Namepath */ + union acpi_operand_object **Where; /* Target of Index */ + UINT8 *IndexPointer; /* Used for Buffers and Strings */ + UINT32 Value; /* Used for Local/Arg/Index/DdbHandle */ } ACPI_OBJECT_REFERENCE; diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h index ab07809..0ef98eb 100644 --- a/sys/contrib/dev/acpica/include/acoutput.h +++ b/sys/contrib/dev/acpica/include/acoutput.h @@ -298,8 +298,12 @@ /* DEBUG_PRINT functions */ -#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist -#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist +#ifndef COMPILER_VA_MACRO + +#define ACPI_DEBUG_PRINT(plist) AcpiDebugPrint plist +#define ACPI_DEBUG_PRINT_RAW(plist) AcpiDebugPrintRaw plist + +#else /* Helper macros for DEBUG_PRINT */ @@ -319,6 +323,11 @@ ACPI_DO_DEBUG_PRINT (AcpiDebugPrintRaw, Level, Line, \ Filename, Modulename, Component, __VA_ARGS__) +#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist +#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist + +#endif + /* * Function entry tracing diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h index 8d972eb..037ffef 100644 --- a/sys/contrib/dev/acpica/include/acpixf.h +++ b/sys/contrib/dev/acpica/include/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20150515 +#define ACPI_CA_VERSION 0x20150619 #include <contrib/dev/acpica/include/acconfig.h> #include <contrib/dev/acpica/include/actypes.h> @@ -202,6 +202,15 @@ ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DoNotUseXsdt, FALSE); ACPI_INIT_GLOBAL (UINT8, AcpiGbl_Use32BitFadtAddresses, FALSE); /* + * Optionally use 32-bit FACS table addresses. + * It is reported that some platforms fail to resume from system suspending + * if 64-bit FACS table address is selected: + * https://bugzilla.kernel.org/show_bug.cgi?id=74021 + * Default is TRUE, favor the 32-bit addresses. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_Use32BitFacsAddresses, TRUE); + +/* * Optionally truncate I/O addresses to 16 bits. Provides compatibility * with other ACPI implementations. NOTE: During ACPICA initialization, * this value is set to TRUE if any Windows OSI strings have been @@ -222,6 +231,11 @@ ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DisableAutoRepair, FALSE); ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DisableSsdtTableInstall, FALSE); /* + * Optionally enable runtime namespace override. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_RuntimeNamespaceOverride, TRUE); + +/* * We keep track of the latest version of Windows that has been requested by * the BIOS. ACPI 5.0. */ @@ -1066,14 +1080,8 @@ AcpiLeaveSleepState ( ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetFirmwareWakingVector ( - UINT32 PhysicalAddress)) - -#if ACPI_MACHINE_WIDTH == 64 -ACPI_HW_DEPENDENT_RETURN_STATUS ( -ACPI_STATUS -AcpiSetFirmwareWakingVector64 ( - UINT64 PhysicalAddress)) -#endif + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64)) /* diff --git a/sys/contrib/dev/acpica/include/acstruct.h b/sys/contrib/dev/acpica/include/acstruct.h index 547921b..3a6faa6 100644 --- a/sys/contrib/dev/acpica/include/acstruct.h +++ b/sys/contrib/dev/acpica/include/acstruct.h @@ -85,6 +85,7 @@ typedef struct acpi_walk_state UINT8 ReturnUsed; UINT8 ScopeDepth; UINT8 PassNumber; /* Parse pass during table load */ + BOOLEAN NamespaceOverride; /* Override existing objects */ UINT8 ResultSize; /* Total elements for the result stack */ UINT8 ResultCount; /* Current number of occupied elements of result stack */ UINT32 AmlOffset; diff --git a/sys/contrib/dev/acpica/include/actbl.h b/sys/contrib/dev/acpica/include/actbl.h index ceef763..f1c3496 100644 --- a/sys/contrib/dev/acpica/include/actbl.h +++ b/sys/contrib/dev/acpica/include/actbl.h @@ -67,6 +67,7 @@ #define ACPI_SIG_DSDT "DSDT" /* Differentiated System Description Table */ #define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */ #define ACPI_SIG_FACS "FACS" /* Firmware ACPI Control Structure */ +#define ACPI_SIG_OSDT "OSDT" /* Override System Description Table */ #define ACPI_SIG_PSDT "PSDT" /* Persistent System Description Table */ #define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Pointer */ #define ACPI_SIG_RSDT "RSDT" /* Root System Description Table */ diff --git a/sys/contrib/dev/acpica/include/actbl1.h b/sys/contrib/dev/acpica/include/actbl1.h index 962324a..3a11553 100644 --- a/sys/contrib/dev/acpica/include/actbl1.h +++ b/sys/contrib/dev/acpica/include/actbl1.h @@ -974,10 +974,22 @@ typedef struct acpi_madt_generic_distributor UINT64 BaseAddress; UINT32 GlobalIrqBase; UINT8 Version; - UINT8 Reserved2[3]; /* Reserved - must be zero */ + UINT8 Reserved2[3]; /* Reserved - must be zero */ } ACPI_MADT_GENERIC_DISTRIBUTOR; +/* Values for Version field above */ + +enum AcpiMadtGicVersion +{ + ACPI_MADT_GIC_VERSION_NONE = 0, + ACPI_MADT_GIC_VERSION_V1 = 1, + ACPI_MADT_GIC_VERSION_V2 = 2, + ACPI_MADT_GIC_VERSION_V3 = 3, + ACPI_MADT_GIC_VERSION_V4 = 4, + ACPI_MADT_GIC_VERSION_RESERVED = 5 /* 5 and greater are reserved */ +}; + /* 13: Generic MSI Frame (ACPI 5.1) */ diff --git a/sys/contrib/dev/acpica/include/actbl2.h b/sys/contrib/dev/acpica/include/actbl2.h index 654495f..6ee36a6 100644 --- a/sys/contrib/dev/acpica/include/actbl2.h +++ b/sys/contrib/dev/acpica/include/actbl2.h @@ -52,8 +52,8 @@ * These tables are not consumed directly by the ACPICA subsystem, but are * included here to support device drivers and the AML disassembler. * - * The tables in this file are defined by third-party specifications, and are - * not defined directly by the ACPI specification itself. + * Generally, the tables in this file are defined by third-party specifications, + * and are not defined directly by the ACPI specification itself. * ******************************************************************************/ @@ -82,6 +82,7 @@ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */ #define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ #define ACPI_SIG_VRTC "VRTC" /* Virtual Real Time Clock Table */ #define ACPI_SIG_WAET "WAET" /* Windows ACPI Emulated devices Table */ @@ -1369,21 +1370,91 @@ enum AcpiSpmiInterfaceTypes /******************************************************************************* * * TCPA - Trusted Computing Platform Alliance table - * Version 1 + * Version 2 + * + * Conforms to "TCG ACPI Specification, Family 1.2 and 2.0", + * December 19, 2014 * - * Conforms to "TCG PC Specific Implementation Specification", - * Version 1.1, August 18, 2003 + * NOTE: There are two versions of the table with the same signature -- + * the client version and the server version. * ******************************************************************************/ -typedef struct acpi_table_tcpa +typedef struct acpi_table_tcpa_client +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 PlatformClass; + UINT32 MinimumLogLength; /* Minimum length for the event log area */ + UINT64 LogAddress; /* Address of the event log area */ + +} ACPI_TABLE_TCPA_CLIENT; + +typedef struct acpi_table_tcpa_server { ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 PlatformClass; UINT16 Reserved; - UINT32 MaxLogLength; /* Maximum length for the event log area */ + UINT64 MinimumLogLength; /* Minimum length for the event log area */ UINT64 LogAddress; /* Address of the event log area */ + UINT16 SpecRevision; + UINT8 DeviceFlags; + UINT8 InterruptFlags; + UINT8 GpeNumber; + UINT8 Reserved2[3]; + UINT32 GlobalInterrupt; + ACPI_GENERIC_ADDRESS Address; + UINT32 Reserved3; + ACPI_GENERIC_ADDRESS ConfigAddress; + UINT8 Group; + UINT8 Bus; /* PCI Bus/Segment/Function numbers */ + UINT8 Device; + UINT8 Function; + +} ACPI_TABLE_TCPA_SERVER; + +/* Values for DeviceFlags above */ + +#define ACPI_TCPA_PCI_DEVICE (1) +#define ACPI_TCPA_BUS_PNP (1<<1) +#define ACPI_TCPA_ADDRESS_VALID (1<<2) + +/* Values for InterruptFlags above */ + +#define ACPI_TCPA_INTERRUPT_MODE (1) +#define ACPI_TCPA_INTERRUPT_POLARITY (1<<1) +#define ACPI_TCPA_SCI_VIA_GPE (1<<2) +#define ACPI_TCPA_GLOBAL_INTERRUPT (1<<3) + + +/******************************************************************************* + * + * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table + * Version 4 + * + * Conforms to "TCG ACPI Specification, Family 1.2 and 2.0", + * December 19, 2014 + * + ******************************************************************************/ + +typedef struct acpi_table_tpm2 +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 PlatformClass; + UINT16 Reserved; + UINT64 ControlAddress; + UINT32 StartMethod; + + /* Platform-specific data follows */ + +} ACPI_TABLE_TPM2; + +/* Values for StartMethod above */ -} ACPI_TABLE_TCPA; +#define ACPI_TPM2_NOT_ALLOWED 0 +#define ACPI_TPM2_START_METHOD 2 +#define ACPI_TPM2_MEMORY_MAPPED 6 +#define ACPI_TPM2_COMMAND_BUFFER 7 +#define ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD 8 /******************************************************************************* diff --git a/sys/contrib/dev/acpica/include/actbl3.h b/sys/contrib/dev/acpica/include/actbl3.h index f575d08..7da6bc6 100644 --- a/sys/contrib/dev/acpica/include/actbl3.h +++ b/sys/contrib/dev/acpica/include/actbl3.h @@ -52,7 +52,8 @@ * These tables are not consumed directly by the ACPICA subsystem, but are * included here to support device drivers and the AML disassembler. * - * The tables in this file are fully defined within the ACPI specification. + * In general, the tables in this file are fully defined within the ACPI + * specification. * ******************************************************************************/ @@ -71,7 +72,6 @@ #define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ #define ACPI_SIG_RASF "RASF" /* RAS Feature table */ #define ACPI_SIG_STAO "STAO" /* Status Override table */ -#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */ #define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ #define ACPI_SIG_XENV "XENV" /* Xen Environment table */ @@ -848,41 +848,6 @@ typedef struct acpi_table_stao /******************************************************************************* * - * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table - * Version 3 - * - * Conforms to "TPM 2.0 Hardware Interface Table (TPM2)" 29 November 2011 - * - ******************************************************************************/ - -typedef struct acpi_table_tpm2 -{ - ACPI_TABLE_HEADER Header; /* Common ACPI table header */ - UINT32 Flags; - UINT64 ControlAddress; - UINT32 StartMethod; - -} ACPI_TABLE_TPM2; - -/* Control area structure (not part of table, pointed to by ControlAddress) */ - -typedef struct acpi_tpm2_control -{ - UINT32 Reserved; - UINT32 Error; - UINT32 Cancel; - UINT32 Start; - UINT64 InterruptControl; - UINT32 CommandSize; - UINT64 CommandAddress; - UINT32 ResponseSize; - UINT64 ResponseAddress; - -} ACPI_TPM2_CONTROL; - - -/******************************************************************************* - * * WPBT - Windows Platform Environment Table (ACPI 6.0) * Version 1 * diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h index 0bee2a7..837c784 100644 --- a/sys/contrib/dev/acpica/include/actypes.h +++ b/sys/contrib/dev/acpica/include/actypes.h @@ -555,14 +555,14 @@ typedef UINT64 ACPI_INTEGER; #define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (UINT32, (a)) == *ACPI_CAST_PTR (UINT32, (b))) #define ACPI_MOVE_NAME(dest,src) (*ACPI_CAST_PTR (UINT32, (dest)) = *ACPI_CAST_PTR (UINT32, (src))) #else -#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE)) -#define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE)) +#define ACPI_COMPARE_NAME(a,b) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE)) +#define ACPI_MOVE_NAME(dest,src) (strncpy (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE)) #endif /* Support for the special RSDP signature (8 characters) */ -#define ACPI_VALIDATE_RSDP_SIG(a) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8)) -#define ACPI_MAKE_RSDP_SIG(dest) (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) +#define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8)) +#define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) /******************************************************************************* @@ -582,6 +582,7 @@ typedef UINT64 ACPI_INTEGER; #define ACPI_NO_ACPI_ENABLE 0x10 #define ACPI_NO_DEVICE_INIT 0x20 #define ACPI_NO_OBJECT_INIT 0x40 +#define ACPI_NO_FACS_INIT 0x80 /* * Initialization state @@ -767,10 +768,6 @@ typedef UINT32 ACPI_EVENT_STATUS; #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 #define ACPI_GPE_CONDITIONAL_ENABLE 2 -#define ACPI_GPE_SAVE_MASK 4 - -#define ACPI_GPE_ENABLE_SAVE (ACPI_GPE_ENABLE | ACPI_GPE_SAVE_MASK) -#define ACPI_GPE_DISABLE_SAVE (ACPI_GPE_DISABLE | ACPI_GPE_SAVE_MASK) /* * GPE info flags - Per GPE @@ -1227,6 +1224,10 @@ UINT32 (*ACPI_INTERFACE_HANDLER) ( #define ACPI_UUID_LENGTH 16 +/* Length of 3-byte PCI class code values when converted back to a string */ + +#define ACPI_PCICLS_STRING_SIZE 7 /* Includes null terminator */ + /* Structures used for device/processor HID, UID, CID, and SUB */ @@ -1255,7 +1256,7 @@ typedef struct acpi_device_info UINT32 Name; /* ACPI object Name */ ACPI_OBJECT_TYPE Type; /* ACPI object Type */ UINT8 ParamCount; /* If a method, required parameter count */ - UINT8 Valid; /* Indicates which optional fields are valid */ + UINT16 Valid; /* Indicates which optional fields are valid */ UINT8 Flags; /* Miscellaneous info */ UINT8 HighestDstates[4]; /* _SxD values: 0xFF indicates not valid */ UINT8 LowestDstates[5]; /* _SxW values: 0xFF indicates not valid */ @@ -1264,6 +1265,7 @@ typedef struct acpi_device_info ACPI_PNP_DEVICE_ID HardwareId; /* _HID value */ ACPI_PNP_DEVICE_ID UniqueId; /* _UID value */ ACPI_PNP_DEVICE_ID SubsystemId; /* _SUB value */ + ACPI_PNP_DEVICE_ID ClassCode; /* _CLS value */ ACPI_PNP_DEVICE_ID_LIST CompatibleIdList; /* _CID list <must be last> */ } ACPI_DEVICE_INFO; @@ -1274,14 +1276,15 @@ typedef struct acpi_device_info /* Flags for Valid field above (AcpiGetObjectInfo) */ -#define ACPI_VALID_STA 0x01 -#define ACPI_VALID_ADR 0x02 -#define ACPI_VALID_HID 0x04 -#define ACPI_VALID_UID 0x08 -#define ACPI_VALID_SUB 0x10 -#define ACPI_VALID_CID 0x20 -#define ACPI_VALID_SXDS 0x40 -#define ACPI_VALID_SXWS 0x80 +#define ACPI_VALID_STA 0x0001 +#define ACPI_VALID_ADR 0x0002 +#define ACPI_VALID_HID 0x0004 +#define ACPI_VALID_UID 0x0008 +#define ACPI_VALID_SUB 0x0010 +#define ACPI_VALID_CID 0x0020 +#define ACPI_VALID_CLS 0x0040 +#define ACPI_VALID_SXDS 0x0100 +#define ACPI_VALID_SXWS 0x0200 /* Flags for _STA return value (CurrentStatus above) */ diff --git a/sys/contrib/dev/acpica/include/acutils.h b/sys/contrib/dev/acpica/include/acutils.h index fe6c057..b7c2a64 100644 --- a/sys/contrib/dev/acpica/include/acutils.h +++ b/sys/contrib/dev/acpica/include/acutils.h @@ -246,116 +246,8 @@ AcpiUtSubsystemShutdown ( void); -/* - * utclib - Local implementations of C library functions - */ -#ifndef ACPI_USE_SYSTEM_CLIBRARY - -ACPI_SIZE -AcpiUtStrlen ( - const char *String); - -char * -AcpiUtStrchr ( - const char *String, - int ch); - -char * -AcpiUtStrcpy ( - char *DstString, - const char *SrcString); - -char * -AcpiUtStrncpy ( - char *DstString, - const char *SrcString, - ACPI_SIZE Count); - -int -AcpiUtMemcmp ( - const char *Buffer1, - const char *Buffer2, - ACPI_SIZE Count); - -int -AcpiUtStrncmp ( - const char *String1, - const char *String2, - ACPI_SIZE Count); - -int -AcpiUtStrcmp ( - const char *String1, - const char *String2); - -char * -AcpiUtStrcat ( - char *DstString, - const char *SrcString); - -char * -AcpiUtStrncat ( - char *DstString, - const char *SrcString, - ACPI_SIZE Count); - -UINT32 -AcpiUtStrtoul ( - const char *String, - char **Terminator, - UINT32 Base); - -char * -AcpiUtStrstr ( - char *String1, - char *String2); - -void * -AcpiUtMemcpy ( - void *Dest, - const void *Src, - ACPI_SIZE Count); - -void * -AcpiUtMemset ( - void *Dest, - UINT8 Value, - ACPI_SIZE Count); - -int -AcpiUtToUpper ( - int c); - -int -AcpiUtToLower ( - int c); - -extern const UINT8 _acpi_ctype[]; - -#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ -#define _ACPI_XS 0x40 /* extra space */ -#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ -#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ -#define _ACPI_DI 0x04 /* '0'-'9' */ -#define _ACPI_LO 0x02 /* 'a'-'z' */ -#define _ACPI_PU 0x10 /* punctuation */ -#define _ACPI_SP 0x08 /* space, tab, CR, LF, VT, FF */ -#define _ACPI_UP 0x01 /* 'A'-'Z' */ -#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ - -#define ACPI_IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) -#define ACPI_IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) -#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) -#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) -#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) -#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) -#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) - -#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ - #define ACPI_IS_ASCII(c) ((c) < 0x80) - /* * utcopy - Object construction and conversion interfaces */ @@ -602,6 +494,11 @@ AcpiUtExecute_CID ( ACPI_NAMESPACE_NODE *DeviceNode, ACPI_PNP_DEVICE_ID_LIST **ReturnCidList); +ACPI_STATUS +AcpiUtExecute_CLS ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID **ReturnId); + /* * utlock - reader/writer locks diff --git a/sys/contrib/dev/acpica/include/platform/acenv.h b/sys/contrib/dev/acpica/include/platform/acenv.h index 88b1ffc..90ace88 100644 --- a/sys/contrib/dev/acpica/include/platform/acenv.h +++ b/sys/contrib/dev/acpica/include/platform/acenv.h @@ -349,28 +349,6 @@ /* We will be linking to the standard Clib functions */ -#define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) -#define ACPI_STRCHR(s1,c) strchr((s1), (c)) -#define ACPI_STRLEN(s) (ACPI_SIZE) strlen((s)) -#define ACPI_STRCPY(d,s) (void) strcpy((d), (s)) -#define ACPI_STRNCPY(d,s,n) (void) strncpy((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRNCMP(d,s,n) strncmp((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRCMP(d,s) strcmp((d), (s)) -#define ACPI_STRCAT(d,s) (void) strcat((d), (s)) -#define ACPI_STRNCAT(d,s,n) strncat((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (ACPI_SIZE)(n)) -#define ACPI_MEMCMP(s1,s2,n) memcmp((const char *)(s1), (const char *)(s2), (ACPI_SIZE)(n)) -#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (ACPI_SIZE)(n)) -#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (ACPI_SIZE)(n)) -#define ACPI_TOUPPER(i) toupper((int) (i)) -#define ACPI_TOLOWER(i) tolower((int) (i)) -#define ACPI_IS_XDIGIT(i) isxdigit((int) (i)) -#define ACPI_IS_DIGIT(i) isdigit((int) (i)) -#define ACPI_IS_SPACE(i) isspace((int) (i)) -#define ACPI_IS_UPPER(i) isupper((int) (i)) -#define ACPI_IS_PRINT(i) isprint((int) (i)) -#define ACPI_IS_ALPHA(i) isalpha((int) (i)) - #else /****************************************************************************** @@ -408,22 +386,6 @@ typedef char *va_list; /* Use the local (ACPICA) definitions of the clib functions */ -#define ACPI_STRSTR(s1,s2) AcpiUtStrstr ((s1), (s2)) -#define ACPI_STRCHR(s1,c) AcpiUtStrchr ((s1), (c)) -#define ACPI_STRLEN(s) (ACPI_SIZE) AcpiUtStrlen ((s)) -#define ACPI_STRCPY(d,s) (void) AcpiUtStrcpy ((d), (s)) -#define ACPI_STRNCPY(d,s,n) (void) AcpiUtStrncpy ((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRNCMP(d,s,n) AcpiUtStrncmp ((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRCMP(d,s) AcpiUtStrcmp ((d), (s)) -#define ACPI_STRCAT(d,s) (void) AcpiUtStrcat ((d), (s)) -#define ACPI_STRNCAT(d,s,n) AcpiUtStrncat ((d), (s), (ACPI_SIZE)(n)) -#define ACPI_STRTOUL(d,s,n) AcpiUtStrtoul ((d), (s), (ACPI_SIZE)(n)) -#define ACPI_MEMCMP(s1,s2,n) AcpiUtMemcmp((const char *)(s1), (const char *)(s2), (ACPI_SIZE)(n)) -#define ACPI_MEMCPY(d,s,n) (void) AcpiUtMemcpy ((d), (s), (ACPI_SIZE)(n)) -#define ACPI_MEMSET(d,v,n) (void) AcpiUtMemset ((d), (v), (ACPI_SIZE)(n)) -#define ACPI_TOUPPER(c) AcpiUtToUpper ((int) (c)) -#define ACPI_TOLOWER(c) AcpiUtToLower ((int) (c)) - #endif /* ACPI_USE_SYSTEM_CLIBRARY */ #ifndef ACPI_FILE diff --git a/sys/contrib/dev/acpica/include/platform/acenvex.h b/sys/contrib/dev/acpica/include/platform/acenvex.h index 6e1130e..c799fd8 100644 --- a/sys/contrib/dev/acpica/include/platform/acenvex.h +++ b/sys/contrib/dev/acpica/include/platform/acenvex.h @@ -56,6 +56,12 @@ #if defined(_LINUX) || defined(__linux__) #include "aclinuxex.h" +#elif defined(_AED_EFI) +#include "acefiex.h" + +#elif defined(_GNU_EFI) +#include "acefiex.h" + #elif defined(__DragonFly__) #include "acdragonflyex.h" diff --git a/sys/contrib/dev/acpica/include/platform/acgcc.h b/sys/contrib/dev/acpica/include/platform/acgcc.h index 2a27445..472b6d7 100644 --- a/sys/contrib/dev/acpica/include/platform/acgcc.h +++ b/sys/contrib/dev/acpica/include/platform/acgcc.h @@ -75,4 +75,8 @@ #undef strchr #endif +/* GCC supports __VA_ARGS__ in macros */ + +#define COMPILER_VA_MACRO 1 + #endif /* __ACGCC_H__ */ diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index 8386c64..61c1d5f 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -160,7 +160,7 @@ db_var_curvnet(struct db_variable *vp, db_expr_t *valuep, int op) return (0); default: - db_printf("db_var_curcpu: unknown operation\n"); + db_printf("db_var_curvnet: unknown operation\n"); return (0); } } diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index 1163681..735065a 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -485,6 +485,9 @@ acpi_ibm_attach(device_t dev) /* Enable per-model events. */ maker = kern_getenv("smbios.system.maker"); product = kern_getenv("smbios.system.product"); + if (maker == NULL || product == NULL) + goto nosmbios; + for (i = 0; i < nitems(acpi_ibm_models); i++) { if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && strcmp(product, acpi_ibm_models[i].product) == 0) { @@ -494,6 +497,8 @@ acpi_ibm_attach(device_t dev) ACPI_SERIAL_END(ibm); } } + +nosmbios: freeenv(maker); freeenv(product); diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c index 1761670..8d94e7b 100644 --- a/sys/dev/acpica/Osd/OsdHardware.c +++ b/sys/dev/acpica/Osd/OsdHardware.c @@ -89,6 +89,10 @@ AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width) { +#ifdef __aarch64__ + /* ARM64TODO: Add pci support */ + return (AE_SUPPORT); +#else if (Width == 64) return (AE_SUPPORT); @@ -99,6 +103,7 @@ AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, PciId->Function, Register, Width / 8); return (AE_OK); +#endif } @@ -107,6 +112,10 @@ AcpiOsWritePciConfiguration (ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width) { +#ifdef __aarch64__ + /* ARM64TODO: Add pci support */ + return (AE_SUPPORT); +#else if (Width == 64) return (AE_SUPPORT); @@ -117,4 +126,5 @@ AcpiOsWritePciConfiguration (ACPI_PCI_ID *PciId, UINT32 Register, Value, Width / 8); return (AE_OK); +#endif } diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 21fccca..e3269db 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -183,7 +183,9 @@ static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc); static void acpi_cpu_startup(void *arg); static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc); static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc); +#if defined(__i386__) || defined(__amd64__) static void acpi_cpu_idle(sbintime_t sbt); +#endif static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context); static void acpi_cpu_quirks(void); static void acpi_cpu_quirks_piix4(void); @@ -475,12 +477,14 @@ enable_idle(struct acpi_cpu_softc *sc) sc->cpu_disable_idle = FALSE; } +#if defined(__i386__) || defined(__amd64__) static int is_idle_disabled(struct acpi_cpu_softc *sc) { return (sc->cpu_disable_idle); } +#endif /* * Disable any entry to the idle function during suspend and re-enable it @@ -999,7 +1003,9 @@ acpi_cpu_startup(void *arg) sc = device_get_softc(cpu_devices[i]); enable_idle(sc); } +#if defined(__i386__) || defined(__amd64__) cpu_idle_hook = acpi_cpu_idle; +#endif } static void @@ -1061,6 +1067,7 @@ acpi_cpu_startup_cx(struct acpi_cpu_softc *sc) } } +#if defined(__i386__) || defined(__amd64__) /* * Idle the CPU in the lowest state possible. This function is called with * interrupts disabled. Note that once it re-enables interrupts, a task @@ -1074,6 +1081,7 @@ acpi_cpu_idle(sbintime_t sbt) struct acpi_cx *cx_next; uint64_t cputicks; uint32_t start_time, end_time; + ACPI_STATUS status; int bm_active, cx_next_idx, i, us; /* @@ -1119,8 +1127,8 @@ acpi_cpu_idle(sbintime_t sbt) */ if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0 && cx_next_idx > sc->cpu_non_c3) { - AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active); - if (bm_active != 0) { + status = AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active); + if (ACPI_SUCCESS(status) && bm_active != 0) { AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1); cx_next_idx = sc->cpu_non_c3; } @@ -1207,6 +1215,7 @@ acpi_cpu_idle(sbintime_t sbt) sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + PM_USEC(end_time)) / 4; } +#endif /* * Re-evaluate the _CST object when we are notified that it changed. @@ -1285,6 +1294,7 @@ acpi_cpu_quirks_piix4(void) #ifdef __i386__ device_t acpi_dev; uint32_t val; + ACPI_STATUS status; acpi_dev = pci_find_device(PCI_VENDOR_INTEL, PCI_DEVICE_82371AB_3); if (acpi_dev != NULL) { @@ -1323,8 +1333,8 @@ acpi_cpu_quirks_piix4(void) val |= PIIX4_STOP_BREAK_MASK; pci_write_config(acpi_dev, PIIX4_DEVACTB_REG, val, 4); } - AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_RLD, &val); - if (val) { + status = AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_RLD, &val); + if (ACPI_SUCCESS(status) && val != 0) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu: PIIX4: reset BRLD_EN_BM\n")); AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 7f3f97d..b034ef7 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -462,7 +462,8 @@ static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, u_char *); /* vendor specific features */ -typedef int probefunc_t(KBDC, struct psm_softc *); +enum probearg { PROBE, REINIT }; +typedef int probefunc_t(struct psm_softc *, enum probearg); static int mouse_id_proc1(KBDC, int, int, int *); static int mouse_ext_command(KBDC, int); @@ -882,7 +883,7 @@ doinitialize(struct psm_softc *sc, mousemode_t *mode) /* Re-enable the mouse. */ for (i = 0; vendortype[i].probefunc != NULL; ++i) if (vendortype[i].model == sc->hw.model) - (*vendortype[i].probefunc)(sc->kbdc, NULL); + (*vendortype[i].probefunc)(sc, REINIT); /* set mouse parameters */ if (mode != (mousemode_t *)NULL) { @@ -893,13 +894,6 @@ doinitialize(struct psm_softc *sc, mousemode_t *mode) set_mouse_resolution(kbdc, mode->resolution); set_mouse_scaling(kbdc, 1); set_mouse_mode(kbdc); - - /* - * Trackpoint settings are lost on resume. - * Restore them here. - */ - if (sc->tphw > 0) - set_trackpoint_parameters(sc); } /* Record sync on the next data packet we see. */ @@ -1388,7 +1382,7 @@ psmprobe(device_t dev) /* other parameters */ for (i = 0; vendortype[i].probefunc != NULL; ++i) - if ((*vendortype[i].probefunc)(sc->kbdc, sc)) { + if ((*vendortype[i].probefunc)(sc, PROBE)) { if (verbose >= 2) printf("psm%d: found %s\n", unit, model_name(vendortype[i].model)); @@ -3731,8 +3725,9 @@ mouse_ext_command(KBDC kbdc, int command) #ifdef notyet /* Logitech MouseMan Cordless II */ static int -enable_lcordless(KDBC kbdc, struct psm_softc *sc) +enable_lcordless(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int status[3]; int ch; @@ -3753,8 +3748,9 @@ enable_lcordless(KDBC kbdc, struct psm_softc *sc) /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */ static int -enable_groller(KBDC kbdc, struct psm_softc *sc) +enable_groller(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int status[3]; /* @@ -3783,15 +3779,16 @@ enable_groller(KBDC kbdc, struct psm_softc *sc) if ((status[1] != '3') || (status[2] != 'D')) return (FALSE); /* FIXME: SmartScroll Mouse has 5 buttons! XXX */ - if (sc != NULL) + if (arg == PROBE) sc->hw.buttons = 4; return (TRUE); } /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */ static int -enable_gmouse(KBDC kbdc, struct psm_softc *sc) +enable_gmouse(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int status[3]; /* @@ -3813,8 +3810,9 @@ enable_gmouse(KBDC kbdc, struct psm_softc *sc) /* ALPS GlidePoint */ static int -enable_aglide(KBDC kbdc, struct psm_softc *sc) +enable_aglide(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int status[3]; /* @@ -3835,9 +3833,10 @@ enable_aglide(KBDC kbdc, struct psm_softc *sc) /* Kensington ThinkingMouse/Trackball */ static int -enable_kmouse(KBDC kbdc, struct psm_softc *sc) +enable_kmouse(struct psm_softc *sc, enum probearg arg) { static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; + KBDC kbdc = sc->kbdc; int status[3]; int id1; int id2; @@ -3888,8 +3887,9 @@ enable_kmouse(KBDC kbdc, struct psm_softc *sc) /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */ static int -enable_mmanplus(KBDC kbdc, struct psm_softc *sc) +enable_mmanplus(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int data[3]; /* the special sequence to enable the fourth button and the roller. */ @@ -3930,7 +3930,7 @@ enable_mmanplus(KBDC kbdc, struct psm_softc *sc) if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0) return (FALSE); - if (sc != NULL) { + if (arg == PROBE) { sc->hw.hwid &= 0x00ff; sc->hw.hwid |= data[2] << 8; /* save model ID */ } @@ -3946,8 +3946,9 @@ enable_mmanplus(KBDC kbdc, struct psm_softc *sc) /* MS IntelliMouse Explorer */ static int -enable_msexplorer(KBDC kbdc, struct psm_softc *sc) +enable_msexplorer(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; static u_char rate0[] = { 200, 100, 80, }; static u_char rate1[] = { 200, 200, 80, }; int id; @@ -3958,7 +3959,7 @@ enable_msexplorer(KBDC kbdc, struct psm_softc *sc) * straight to Explorer mode, but need to be set to Intelli mode * first. */ - enable_msintelli(kbdc, sc); + enable_msintelli(sc, arg); /* the special sequence to enable the extra buttons and the roller. */ for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i) @@ -3969,7 +3970,7 @@ enable_msexplorer(KBDC kbdc, struct psm_softc *sc) if (id != PSM_EXPLORER_ID) return (FALSE); - if (sc != NULL) { + if (arg == PROBE) { sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */ sc->hw.hwid = id; } @@ -3992,15 +3993,15 @@ enable_msexplorer(KBDC kbdc, struct psm_softc *sc) return (TRUE); } -/* MS IntelliMouse */ +/* + * MS IntelliMouse + * Logitech MouseMan+ and FirstMouse+ will also respond to this + * probe routine and act like IntelliMouse. + */ static int -enable_msintelli(KBDC kbdc, struct psm_softc *sc) +enable_msintelli(struct psm_softc *sc, enum probearg arg) { - /* - * Logitech MouseMan+ and FirstMouse+ will also respond to this - * probe routine and act like IntelliMouse. - */ - + KBDC kbdc = sc->kbdc; static u_char rate[] = { 200, 100, 80, }; int id; int i; @@ -4014,7 +4015,7 @@ enable_msintelli(KBDC kbdc, struct psm_softc *sc) if (id != PSM_INTELLI_ID) return (FALSE); - if (sc != NULL) { + if (arg == PROBE) { sc->hw.buttons = 3; sc->hw.hwid = id; } @@ -4022,15 +4023,15 @@ enable_msintelli(KBDC kbdc, struct psm_softc *sc) return (TRUE); } -/* A4 Tech 4D Mouse */ +/* + * A4 Tech 4D Mouse + * Newer wheel mice from A4 Tech may use the 4D+ protocol. + */ static int -enable_4dmouse(KBDC kbdc, struct psm_softc *sc) +enable_4dmouse(struct psm_softc *sc, enum probearg arg) { - /* - * Newer wheel mice from A4 Tech may use the 4D+ protocol. - */ - static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; + KBDC kbdc = sc->kbdc; int id; int i; @@ -4046,7 +4047,7 @@ enable_4dmouse(KBDC kbdc, struct psm_softc *sc) if (id != PSM_4DMOUSE_ID) return (FALSE); - if (sc != NULL) { + if (arg == PROBE) { sc->hw.buttons = 3; /* XXX some 4D mice have 4? */ sc->hw.hwid = id; } @@ -4054,14 +4055,15 @@ enable_4dmouse(KBDC kbdc, struct psm_softc *sc) return (TRUE); } -/* A4 Tech 4D+ Mouse */ +/* + * A4 Tech 4D+ Mouse + * Newer wheel mice from A4 Tech seem to use this protocol. + * Older models are recognized as either 4D Mouse or IntelliMouse. + */ static int -enable_4dplus(KBDC kbdc, struct psm_softc *sc) +enable_4dplus(struct psm_softc *sc, enum probearg arg) { - /* - * Newer wheel mice from A4 Tech seem to use this protocol. - * Older models are recognized as either 4D Mouse or IntelliMouse. - */ + KBDC kbdc = sc->kbdc; int id; /* @@ -4084,7 +4086,7 @@ enable_4dplus(KBDC kbdc, struct psm_softc *sc) return (FALSE); } - if (sc != NULL) { + if (arg == PROBE) { sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3; sc->hw.hwid = id; } @@ -4543,8 +4545,9 @@ synaptics_set_mode(struct psm_softc *sc, int mode_byte) { } static int -enable_synaptics(KBDC kbdc, struct psm_softc *sc) +enable_synaptics(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; synapticshw_t synhw; int status[3]; int buttons; @@ -4828,20 +4831,20 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) return (FALSE); } - if (sc != NULL) + if (arg == PROBE) sc->synhw = synhw; if (!synaptics_support) return (FALSE); + synaptics_set_mode(sc, synaptics_preferred_mode(sc)); + + if (trackpoint_support && synhw.capPassthrough) { + enable_trackpoint(sc, arg); + } + VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); - if (sc != NULL) { - synaptics_set_mode(sc, synaptics_preferred_mode(sc)); - if (trackpoint_support && synhw.capPassthrough) { - synaptics_passthrough_on(sc); - enable_trackpoint(kbdc, sc); - synaptics_passthrough_off(sc); - } + if (arg == PROBE) { /* Create sysctl tree. */ synaptics_sysctl_create_tree(sc); sc->hw.buttons = buttons; @@ -5086,25 +5089,37 @@ set_trackpoint_parameters(struct psm_softc *sc) } static int -enable_trackpoint(KBDC kbdc, struct psm_softc *sc) +enable_trackpoint(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int id; + /* + * If called from enable_synaptics(), make sure that passthrough + * mode is enabled so we can reach the trackpoint. + * However, passthrough mode must be disabled before setting the + * trackpoint parameters, as rackpoint_command() enables and disables + * passthrough mode on its own. + */ + if (sc->synhw.capPassthrough) + synaptics_passthrough_on(sc); + if (send_aux_command(kbdc, 0xe1) != PSM_ACK || read_aux_data(kbdc) != 0x01) - return (FALSE); + goto no_trackpoint; id = read_aux_data(kbdc); if (id < 0x01) - return (FALSE); - if (sc != NULL) + goto no_trackpoint; + if (arg == PROBE) sc->tphw = id; if (!trackpoint_support) - return (FALSE); + goto no_trackpoint; - if (sc != NULL) { - /* Create sysctl tree. */ - trackpoint_sysctl_create_tree(sc); + if (sc->synhw.capPassthrough) + synaptics_passthrough_off(sc); + if (arg == PROBE) { + trackpoint_sysctl_create_tree(sc); /* * Don't overwrite hwid and buttons when we are * a guest device. @@ -5115,13 +5130,22 @@ enable_trackpoint(KBDC kbdc, struct psm_softc *sc) } } + set_trackpoint_parameters(sc); + return (TRUE); + +no_trackpoint: + if (sc->synhw.capPassthrough) + synaptics_passthrough_off(sc); + + return (FALSE); } /* Interlink electronics VersaPad */ static int -enable_versapad(KBDC kbdc, struct psm_softc *sc) +enable_versapad(struct psm_softc *sc, enum probearg arg) { + KBDC kbdc = sc->kbdc; int data[3]; set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */ diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c index 00e367a..2a2a81c 100644 --- a/sys/dev/bxe/bxe.c +++ b/sys/dev/bxe/bxe.c @@ -726,7 +726,6 @@ static __noinline int bxe_nic_unload(struct bxe_softc *sc, uint8_t keep_link); static void bxe_handle_sp_tq(void *context, int pending); -static void bxe_handle_rx_mode_tq(void *context, int pending); static void bxe_handle_fp_tq(void *context, int pending); @@ -1174,7 +1173,17 @@ bxe_release_hw_lock(struct bxe_softc *sc, REG_WR(sc, hw_lock_control_reg, resource_bit); return (0); } +static void bxe_acquire_phy_lock(struct bxe_softc *sc) +{ + BXE_PHY_LOCK(sc); + bxe_acquire_hw_lock(sc,HW_LOCK_RESOURCE_MDIO); +} +static void bxe_release_phy_lock(struct bxe_softc *sc) +{ + bxe_release_hw_lock(sc,HW_LOCK_RESOURCE_MDIO); + BXE_PHY_UNLOCK(sc); +} /* * Per pf misc lock must be acquired before the per port mcp lock. Otherwise, * had we done things the other way around, if two pfs from the same port @@ -4764,28 +4773,6 @@ bxe_handle_chip_tq(void *context, switch (work) { - case CHIP_TQ_START: - if ((if_getflags(sc->ifp) & IFF_UP) && - !(if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING)) { - /* start the interface */ - BLOGD(sc, DBG_LOAD, "Starting the interface...\n"); - BXE_CORE_LOCK(sc); - bxe_init_locked(sc); - BXE_CORE_UNLOCK(sc); - } - break; - - case CHIP_TQ_STOP: - if (!(if_getflags(sc->ifp) & IFF_UP) && - (if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING)) { - /* bring down the interface */ - BLOGD(sc, DBG_LOAD, "Stopping the interface...\n"); - bxe_periodic_stop(sc); - BXE_CORE_LOCK(sc); - bxe_stop_locked(sc); - BXE_CORE_UNLOCK(sc); - } - break; case CHIP_TQ_REINIT: if (if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) { @@ -4859,21 +4846,22 @@ bxe_ioctl(if_t ifp, /* toggle the interface state up or down */ BLOGD(sc, DBG_IOCTL, "Received SIOCSIFFLAGS ioctl\n"); + BXE_CORE_LOCK(sc); /* check if the interface is up */ if (if_getflags(ifp) & IFF_UP) { if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { /* set the receive mode flags */ bxe_set_rx_mode(sc); } else { - atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_START); - taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task); + bxe_init_locked(sc); } } else { if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_STOP); - taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task); + bxe_periodic_stop(sc); + bxe_stop_locked(sc); } } + BXE_CORE_UNLOCK(sc); break; @@ -4885,7 +4873,9 @@ bxe_ioctl(if_t ifp, /* check if the interface is up */ if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { /* set the receive mode flags */ + BXE_CORE_LOCK(sc); bxe_set_rx_mode(sc); + BXE_CORE_UNLOCK(sc); } break; @@ -5044,8 +5034,11 @@ bxe_ioctl(if_t ifp, if (reinit && (if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING)) { BLOGD(sc, DBG_LOAD | DBG_IOCTL, "Re-initializing hardware from IOCTL change\n"); - atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_REINIT); - taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task); + bxe_periodic_stop(sc); + BXE_CORE_LOCK(sc); + bxe_stop_locked(sc); + bxe_init_locked(sc); + BXE_CORE_UNLOCK(sc); } return (error); @@ -7487,8 +7480,7 @@ bxe_attn_int_asserted(struct bxe_softc *sc, if (asserted & ATTN_HARD_WIRED_MASK) { if (asserted & ATTN_NIG_FOR_FUNC) { - BXE_PHY_LOCK(sc); - + bxe_acquire_phy_lock(sc); /* save nig interrupt mask */ nig_mask = REG_RD(sc, nig_int_mask_addr); @@ -7581,7 +7573,7 @@ bxe_attn_int_asserted(struct bxe_softc *sc, REG_WR(sc, nig_int_mask_addr, nig_mask); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } } @@ -8339,10 +8331,10 @@ bxe_attn_int_deasserted3(struct bxe_softc *sc, if (sc->link_vars.periodic_flags & ELINK_PERIODIC_FLAGS_LINK_EVENT) { /* sync with link */ - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); sc->link_vars.periodic_flags &= ~ELINK_PERIODIC_FLAGS_LINK_EVENT; - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); if (IS_MF(sc)) ; // XXX bxe_link_sync_notify(sc); bxe_link_report(sc); @@ -8535,9 +8527,9 @@ bxe_attn_int_deasserted0(struct bxe_softc *sc, } if ((attn & sc->link_vars.aeu_int_mask) && sc->port.pmf) { - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); elink_handle_module_detect_int(&sc->link_params); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } if (attn & HW_INTERRUT_ASSERT_SET_0) { @@ -9564,11 +9556,6 @@ bxe_interrupt_detach(struct bxe_softc *sc) } } - if (sc->rx_mode_tq) { - taskqueue_drain(sc->rx_mode_tq, &sc->rx_mode_tq_task); - taskqueue_free(sc->rx_mode_tq); - sc->rx_mode_tq = NULL; - } if (sc->sp_tq) { taskqueue_drain(sc->sp_tq, &sc->sp_tq_task); @@ -9602,14 +9589,6 @@ bxe_interrupt_attach(struct bxe_softc *sc) taskqueue_start_threads(&sc->sp_tq, 1, PWAIT, /* lower priority */ "%s", sc->sp_tq_name); - snprintf(sc->rx_mode_tq_name, sizeof(sc->rx_mode_tq_name), - "bxe%d_rx_mode_tq", sc->unit); - TASK_INIT(&sc->rx_mode_tq_task, 0, bxe_handle_rx_mode_tq, sc); - sc->rx_mode_tq = taskqueue_create_fast(sc->rx_mode_tq_name, M_NOWAIT, - taskqueue_thread_enqueue, - &sc->rx_mode_tq); - taskqueue_start_threads(&sc->rx_mode_tq, 1, PWAIT, /* lower priority */ - "%s", sc->rx_mode_tq_name); for (i = 0; i < sc->num_queues; i++) { fp = &sc->fp[i]; @@ -12363,9 +12342,9 @@ bxe_link_report_locked(struct bxe_softc *sc) static void bxe_link_report(struct bxe_softc *sc) { - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); bxe_link_report_locked(sc); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } static void @@ -12481,7 +12460,7 @@ bxe_initial_phy_init(struct bxe_softc *sc, sc->link_params.feature_config_flags |= feat; } - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); if (load_mode == LOAD_DIAG) { lp->loopback_mode = ELINK_LOOPBACK_XGXS; @@ -12502,7 +12481,7 @@ bxe_initial_phy_init(struct bxe_softc *sc, rc = elink_phy_init(&sc->link_params, &sc->link_vars); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); bxe_calc_fc_adv(sc); @@ -12546,6 +12525,7 @@ bxe_init_mcast_macs_list(struct bxe_softc *sc, BLOGE(sc, "Failed to allocate temp mcast list\n"); return (-1); } + bzero(mta, (sizeof(unsigned char) * ETHER_ADDR_LEN * mc_count)); mc_mac = malloc(sizeof(*mc_mac) * mc_count, M_DEVBUF, (M_NOWAIT | M_ZERO)); @@ -12554,12 +12534,13 @@ bxe_init_mcast_macs_list(struct bxe_softc *sc, BLOGE(sc, "Failed to allocate temp mcast list\n"); return (-1); } + bzero(mc_mac, (sizeof(*mc_mac) * mc_count)); if_multiaddr_array(ifp, mta, &mcnt, mc_count); /* mta and mcnt not expected to be different */ for(i=0; i< mcnt; i++) { - bcopy((mta + (i * ETHER_ADDR_LEN)), mc_mac->mac, ETHER_ADDR_LEN); + mc_mac->mac = (uint8_t *)(mta + (i * ETHER_ADDR_LEN)); ECORE_LIST_PUSH_TAIL(&mc_mac->link, &p->mcast_list); BLOGD(sc, DBG_LOAD, @@ -12604,6 +12585,7 @@ bxe_set_mc_list(struct bxe_softc *sc) rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_DEL); if (rc < 0) { BLOGE(sc, "Failed to clear multicast configuration: %d\n", rc); + BXE_MCAST_UNLOCK(sc); return (rc); } @@ -12694,18 +12676,13 @@ bxe_set_uc_list(struct bxe_softc *sc) } static void -bxe_handle_rx_mode_tq(void *context, - int pending) +bxe_set_rx_mode(struct bxe_softc *sc) { - struct bxe_softc *sc = (struct bxe_softc *)context; if_t ifp = sc->ifp; uint32_t rx_mode = BXE_RX_MODE_NORMAL; - BXE_CORE_LOCK(sc); - if (sc->state != BXE_STATE_OPEN) { BLOGD(sc, DBG_SP, "state is %x, returning\n", sc->state); - BXE_CORE_UNLOCK(sc); return; } @@ -12747,7 +12724,6 @@ bxe_handle_rx_mode_tq(void *context, if (bxe_test_bit(ECORE_FILTER_RX_MODE_PENDING, &sc->sp_state)) { BLOGD(sc, DBG_LOAD, "Scheduled setting rx_mode with ECORE...\n"); bxe_set_bit(ECORE_FILTER_RX_MODE_SCHED, &sc->sp_state); - BXE_CORE_UNLOCK(sc); return; } @@ -12767,14 +12743,8 @@ bxe_handle_rx_mode_tq(void *context, } #endif - BXE_CORE_UNLOCK(sc); } -static void -bxe_set_rx_mode(struct bxe_softc *sc) -{ - taskqueue_enqueue(sc->rx_mode_tq, &sc->rx_mode_tq_task); -} /* update flags in shmem */ static void @@ -12845,13 +12815,13 @@ bxe_periodic_callout_func(void *xsc) */ mb(); if (sc->port.pmf) { - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); elink_period_func(&sc->link_params, &sc->link_vars); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } } - if (IS_PF(sc) && !BXE_NOMCP(sc)) { + if (IS_PF(sc) && !(sc->flags & BXE_NO_PULSE)) { int mb_idx = SC_FW_MB_IDX(sc); uint32_t drv_pulse; uint32_t mcp_pulse; @@ -12995,6 +12965,11 @@ bxe_nic_load(struct bxe_softc *sc, } } + /* set ALWAYS_ALIVE bit in shmem */ + sc->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE; + bxe_drv_pulse(sc); + sc->flags |= BXE_NO_PULSE; + /* attach interrupts */ if (bxe_interrupt_attach(sc) != 0) { sc->state = BXE_STATE_CLOSED; @@ -16750,10 +16725,10 @@ bxe_common_init_phy(struct bxe_softc *sc) shmem2_base[1] = SHMEM2_RD(sc, other_shmem2_base_addr); } - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); elink_common_init_phy(sc, shmem_base, shmem2_base, sc->devinfo.chip_id, 0); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } static void @@ -18630,9 +18605,9 @@ static void bxe_link_reset(struct bxe_softc *sc) { if (!BXE_NOMCP(sc)) { - BXE_PHY_LOCK(sc); + bxe_acquire_phy_lock(sc); elink_lfa_reset(&sc->link_params, &sc->link_vars); - BXE_PHY_UNLOCK(sc); + bxe_release_phy_lock(sc); } else { if (!CHIP_REV_IS_SLOW(sc)) { BLOGW(sc, "Bootcode is missing - cannot reset link\n"); diff --git a/sys/dev/bxe/bxe.h b/sys/dev/bxe/bxe.h index eb695d0..5fb31a3 100644 --- a/sys/dev/bxe/bxe.h +++ b/sys/dev/bxe/bxe.h @@ -1400,6 +1400,7 @@ struct bxe_softc { //#define BXE_SAFC_TX_FLAG 0x00000400 #define BXE_MF_FUNC_DIS 0x00000800 #define BXE_TX_SWITCHING 0x00001000 +#define BXE_NO_PULSE 0x00002000 unsigned long debug; /* per-instance debug logging config */ @@ -1429,11 +1430,6 @@ struct bxe_softc { struct taskqueue *sp_tq; char sp_tq_name[32]; - /* set rx_mode asynchronous taskqueue */ - struct task rx_mode_tq_task; - struct taskqueue *rx_mode_tq; - char rx_mode_tq_name[32]; - struct bxe_fastpath fp[MAX_RSS_CHAINS]; struct bxe_sp_objs sp_objs[MAX_RSS_CHAINS]; diff --git a/sys/dev/bxe/ecore_reg.h b/sys/dev/bxe/ecore_reg.h index b256e78..850390c 100644 --- a/sys/dev/bxe/ecore_reg.h +++ b/sys/dev/bxe/ecore_reg.h @@ -1965,6 +1965,7 @@ __FBSDID("$FreeBSD$"); #define MISC_SPIO_SPIO5 0x20 #define HW_LOCK_MAX_RESOURCE_VALUE 31 #define HW_LOCK_RESOURCE_DRV_FLAGS 10 +#define HW_LOCK_RESOURCE_MDIO 0 #define HW_LOCK_RESOURCE_GPIO 1 #define HW_LOCK_RESOURCE_NVRAM 12 #define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3 diff --git a/sys/dev/bxe/ecore_sp.c b/sys/dev/bxe/ecore_sp.c index b716085..2685453 100644 --- a/sys/dev/bxe/ecore_sp.c +++ b/sys/dev/bxe/ecore_sp.c @@ -474,7 +474,7 @@ static void __ecore_vlan_mac_h_exec_pending(struct bxe_softc *sc, o->head_exe_request = FALSE; o->saved_ramrod_flags = 0; rc = ecore_exe_queue_step(sc, &o->exe_queue, &ramrod_flags); - if (rc != ECORE_SUCCESS) { + if ((rc != ECORE_SUCCESS) && (rc != ECORE_PENDING)) { ECORE_ERR("execution of pending commands failed with rc %d\n", rc); #ifdef ECORE_STOP_ON_ERROR diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 2655dae..c178297 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -206,6 +206,9 @@ enum { INTR_OFLD_RXQ = (1 << 5), /* All TOE rxq's take interrupts */ INTR_NM_RXQ = (1 << 6), /* All netmap rxq's take interrupts */ INTR_ALL = (INTR_RXQ | INTR_OFLD_RXQ | INTR_NM_RXQ), + + /* adapter debug_flags */ + DF_DUMP_MBOX = (1 << 0), }; #define IS_DOOMED(pi) ((pi)->flags & DOOMED) @@ -762,6 +765,7 @@ struct adapter { int active_ulds; /* ULDs activated on this adapter */ #endif int flags; + int debug_flags; char ifp_lockname[16]; struct mtx ifp_lock; @@ -846,6 +850,24 @@ struct adapter { #define TXQ_LOCK_ASSERT_OWNED(txq) EQ_LOCK_ASSERT_OWNED(&(txq)->eq) #define TXQ_LOCK_ASSERT_NOTOWNED(txq) EQ_LOCK_ASSERT_NOTOWNED(&(txq)->eq) +#define CH_DUMP_MBOX(sc, mbox, data_reg) \ + do { \ + if (sc->debug_flags & DF_DUMP_MBOX) { \ + log(LOG_NOTICE, \ + "%s mbox %u: %016llx %016llx %016llx %016llx " \ + "%016llx %016llx %016llx %016llx\n", \ + device_get_nameunit(sc->dev), mbox, \ + (unsigned long long)t4_read_reg64(sc, data_reg), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 8), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 16), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 24), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 32), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 40), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 48), \ + (unsigned long long)t4_read_reg64(sc, data_reg + 56)); \ + } \ + } while (0) + #define for_each_txq(pi, iter, q) \ for (q = &pi->adapter->sge.txq[pi->first_txq], iter = 0; \ iter < pi->ntxq; ++iter, ++q) diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index e2efb78..d140276 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -262,6 +262,8 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, for (i = 0; i < size; i += 8, p++) t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p)); + CH_DUMP_MBOX(adap, mbox, data_reg); + t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW)); t4_read_reg(adap, ctl_reg); /* flush write */ @@ -287,6 +289,8 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, continue; } + CH_DUMP_MBOX(adap, mbox, data_reg); + res = t4_read_reg64(adap, data_reg); if (G_FW_CMD_OP(res >> 32) == FW_DEBUG_CMD) { fw_asrt(adap, data_reg); diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index b164cce..5c88059 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -585,6 +585,9 @@ t4_attach(device_t dev) sc = device_get_softc(dev); sc->dev = dev; +#ifdef INVARIANTS + sc->debug_flags = DF_DUMP_MBOX; +#endif pci_enable_busmaster(dev); if (pci_find_cap(dev, PCIY_EXPRESS, &i) == 0) { @@ -4603,6 +4606,9 @@ t4_sysctls(struct adapter *sc) SYSCTL_ADD_INT(ctx, children, OID_AUTO, "lro_timeout", CTLFLAG_RW, &sc->lro_timeout, 0, "lro inactive-flush timeout (in us)"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "debug_flags", CTLFLAG_RW, + &sc->debug_flags, 0, "flags to enable runtime debugging"); + #ifdef SBUF_DRAIN /* * dev.t4nex.X.misc. Marked CTLFLAG_SKIP to avoid information overload. diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c index a473031..356ccc5 100644 --- a/sys/dev/drm2/i915/i915_gem.c +++ b/sys/dev/drm2/i915/i915_gem.c @@ -1874,7 +1874,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, map = &p->p_vmspace->vm_map; size = round_page(args->size); PROC_LOCK(p); - if (map->size + size > lim_cur(p, RLIMIT_VMEM)) { + if (map->size + size > lim_cur_proc(p, RLIMIT_VMEM)) { PROC_UNLOCK(p); error = -ENOMEM; goto out; @@ -3175,9 +3175,6 @@ i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex, bool *fresh) if (m->valid != VM_PAGE_BITS_ALL) { if (vm_pager_has_page(object, pindex, NULL, NULL)) { rv = vm_pager_get_pages(object, &m, 1, 0); - m = vm_page_lookup(object, pindex); - if (m == NULL) - return (NULL); if (rv != VM_PAGER_OK) { vm_page_lock(m); vm_page_free(m); diff --git a/sys/dev/drm2/ttm/ttm_page_alloc.c b/sys/dev/drm2/ttm/ttm_page_alloc.c index 246afdf..75abd10 100644 --- a/sys/dev/drm2/ttm/ttm_page_alloc.c +++ b/sys/dev/drm2/ttm/ttm_page_alloc.c @@ -155,6 +155,66 @@ ttm_caching_state_to_vm(enum ttm_caching_state cstate) panic("caching state %d\n", cstate); } +static vm_page_t +ttm_vm_page_alloc_dma32(int req, vm_memattr_t memattr) +{ + vm_page_t p; + int tries; + + for (tries = 0; ; tries++) { + p = vm_page_alloc_contig(NULL, 0, req, 1, 0, 0xffffffff, + PAGE_SIZE, 0, memattr); + if (p != NULL || tries > 2) + return (p); + + /* + * Before growing the cache see if this is just a normal + * memory shortage. + */ + VM_WAIT; + vm_pageout_grow_cache(tries, 0, 0xffffffff); + } +} + +static vm_page_t +ttm_vm_page_alloc_any(int req, vm_memattr_t memattr) +{ + vm_page_t p; + + while (1) { + p = vm_page_alloc(NULL, 0, req); + if (p != NULL) + break; + VM_WAIT; + } + pmap_page_set_memattr(p, memattr); + return (p); +} + +static vm_page_t +ttm_vm_page_alloc(int flags, enum ttm_caching_state cstate) +{ + vm_page_t p; + vm_memattr_t memattr; + int req; + + memattr = ttm_caching_state_to_vm(cstate); + req = VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ; + if ((flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0) + req |= VM_ALLOC_ZERO; + + if ((flags & TTM_PAGE_FLAG_DMA32) != 0) + p = ttm_vm_page_alloc_dma32(req, memattr); + else + p = ttm_vm_page_alloc_any(req, memattr); + + if (p != NULL) { + p->oflags &= ~VPO_UNMANAGED; + p->flags |= PG_FICTITIOUS; + } + return (p); +} + static void ttm_pool_kobj_release(struct ttm_pool_manager *m) { @@ -461,14 +521,6 @@ static void ttm_handle_caching_state_failure(struct pglist *pages, } } -static vm_paddr_t -ttm_alloc_high_bound(int ttm_alloc_flags) -{ - - return ((ttm_alloc_flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff : - VM_MAX_ADDRESS); -} - /** * Allocate new pages with correct caching. * @@ -481,32 +533,17 @@ static int ttm_alloc_new_pages(struct pglist *pages, int ttm_alloc_flags, vm_page_t *caching_array; vm_page_t p; int r = 0; - unsigned i, cpages, aflags; + unsigned i, cpages; unsigned max_cpages = min(count, (unsigned)(PAGE_SIZE/sizeof(vm_page_t))); - int tries; - aflags = VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ | - ((ttm_alloc_flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ? - VM_ALLOC_ZERO : 0); - /* allocate array for page caching change */ caching_array = malloc(max_cpages * sizeof(vm_page_t), M_TEMP, M_WAITOK | M_ZERO); for (i = 0, cpages = 0; i < count; ++i) { - tries = 0; -retry: - p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0, - ttm_alloc_high_bound(ttm_alloc_flags), - PAGE_SIZE, 0, ttm_caching_state_to_vm(cstate)); + p = ttm_vm_page_alloc(ttm_alloc_flags, cstate); if (!p) { - if (tries < 3) { - vm_pageout_grow_cache(tries, 0, - ttm_alloc_high_bound(ttm_alloc_flags)); - tries++; - goto retry; - } printf("[TTM] Unable to get page %u\n", i); /* store already allocated pages in the pool after @@ -522,8 +559,6 @@ retry: r = -ENOMEM; goto out; } - p->oflags &= ~VPO_UNMANAGED; - p->flags |= PG_FICTITIOUS; #ifdef CONFIG_HIGHMEM /* KIB: nop */ /* gfp flags of highmem page should never be dma32 so we @@ -705,34 +740,18 @@ static int ttm_get_pages(vm_page_t *pages, unsigned npages, int flags, struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct pglist plist; vm_page_t p = NULL; - int gfp_flags, aflags; + int gfp_flags; unsigned count; int r; - int tries; - - aflags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | - ((flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ? VM_ALLOC_ZERO : 0); /* No pool for cached pages */ if (pool == NULL) { for (r = 0; r < npages; ++r) { - tries = 0; -retry: - p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0, - ttm_alloc_high_bound(flags), PAGE_SIZE, - 0, ttm_caching_state_to_vm(cstate)); + p = ttm_vm_page_alloc(flags, cstate); if (!p) { - if (tries < 3) { - vm_pageout_grow_cache(tries, 0, - ttm_alloc_high_bound(flags)); - tries++; - goto retry; - } printf("[TTM] Unable to allocate page\n"); return -ENOMEM; } - p->oflags &= ~VPO_UNMANAGED; - p->flags |= PG_FICTITIOUS; pages[r] = p; } return 0; diff --git a/sys/dev/filemon/filemon.h b/sys/dev/filemon/filemon.h index 95d2ef3..b3fa061 100644 --- a/sys/dev/filemon/filemon.h +++ b/sys/dev/filemon/filemon.h @@ -30,5 +30,5 @@ #define FILEMON_SET_FD _IOWR('S', 1, int) #define FILEMON_SET_PID _IOWR('S', 2, pid_t) -#define FILEMON_VERSION 4 /* output format +#define FILEMON_VERSION 5 /* output format (bump when adding record types) */ diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 2c6f20e..4a1259a 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -28,6 +28,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/sx.h> + #include "opt_compat.h" #if __FreeBSD_version > 800032 @@ -84,13 +86,17 @@ filemon_pid_check(struct proc *p) { struct filemon *filemon; - while (p->p_pptr) { + sx_slock(&proctree_lock); + while (p != initproc) { TAILQ_FOREACH(filemon, &filemons_inuse, link) { - if (p->p_pid == filemon->pid) + if (p->p_pid == filemon->pid) { + sx_sunlock(&proctree_lock); return (filemon); + } } - p = p->p_pptr; + p = proc_realparent(p); } + sx_sunlock(&proctree_lock); return (NULL); } @@ -316,6 +322,68 @@ filemon_wrapper_open(struct thread *td, struct open_args *uap) } static int +filemon_wrapper_openat(struct thread *td, struct openat_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = sys_openat(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->path, filemon->fname1, + sizeof(filemon->fname1), &done); + + filemon->fname2[0] = '\0'; + if (filemon->fname1[0] != '/' && uap->fd != AT_FDCWD) { + /* + * rats - we cannot do too much about this. + * the trace should show a dir we read + * recently.. output an A record as a clue + * until we can do better. + */ + len = snprintf(filemon->msgbufr, + sizeof(filemon->msgbufr), "A %d %s\n", + curproc->p_pid, filemon->fname1); + filemon_output(filemon, filemon->msgbufr, len); + } + if (uap->flag & O_RDWR) { + /* + * We'll get the W record below, but need + * to also output an R to distingish from + * O_WRONLY. + */ + len = snprintf(filemon->msgbufr, + sizeof(filemon->msgbufr), "R %d %s%s\n", + curproc->p_pid, filemon->fname2, filemon->fname1); + filemon_output(filemon, filemon->msgbufr, len); + } + + + len = snprintf(filemon->msgbufr, + sizeof(filemon->msgbufr), "%c %d %s%s\n", + (uap->flag & O_ACCMODE) ? 'W':'R', + curproc->p_pid, filemon->fname2, filemon->fname1); + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return (ret); +} + +static int filemon_wrapper_rename(struct thread *td, struct rename_args *uap) { int ret; @@ -669,6 +737,7 @@ filemon_wrapper_install(void) sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve; sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; + sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat; sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; @@ -687,6 +756,7 @@ filemon_wrapper_install(void) sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve; sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; + sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat; sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; @@ -713,6 +783,7 @@ filemon_wrapper_deinstall(void) sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve; sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[SYS_open].sy_call = (sy_call_t *)sys_open; + sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename; sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat; sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink; @@ -731,6 +802,7 @@ filemon_wrapper_deinstall(void) sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve; sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open; + sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename; sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat; sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink; diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c index 6646b7d..1dbb526 100644 --- a/sys/dev/gpio/ofw_gpiobus.c +++ b/sys/dev/gpio/ofw_gpiobus.c @@ -56,6 +56,14 @@ ofw_gpiobus_add_fdt_child(device_t bus, const char *drvname, phandle_t child) struct ofw_gpiobus_devinfo *dinfo; /* + * Check to see if we already have a child for @p child, and if so + * return it. + */ + childdev = ofw_bus_find_child_device_by_phandle(bus, child); + if (childdev != NULL) + return (childdev); + + /* * Set up the GPIO child and OFW bus layer devinfo and add it to bus. */ childdev = device_add_child(bus, drvname, -1); diff --git a/sys/dev/hwpmc/hwpmc_armv7.c b/sys/dev/hwpmc/hwpmc_armv7.c index 66d4971..469eca8 100644 --- a/sys/dev/hwpmc/hwpmc_armv7.c +++ b/sys/dev/hwpmc/hwpmc_armv7.c @@ -39,9 +39,6 @@ __FBSDID("$FreeBSD$"); #include <machine/pmc_mdep.h> #include <machine/cpu.h> -#define CPU_ID_CORTEX_VER_MASK 0xff -#define CPU_ID_CORTEX_VER_SHIFT 4 - static int armv7_npmcs; struct armv7_event_code_map { @@ -49,49 +46,11 @@ struct armv7_event_code_map { uint8_t pe_code; }; -const struct armv7_event_code_map armv7_event_codes[] = { - { PMC_EV_ARMV7_PMNC_SW_INCR, 0x00 }, - { PMC_EV_ARMV7_L1_ICACHE_REFILL, 0x01 }, - { PMC_EV_ARMV7_ITLB_REFILL, 0x02 }, - { PMC_EV_ARMV7_L1_DCACHE_REFILL, 0x03 }, - { PMC_EV_ARMV7_L1_DCACHE_ACCESS, 0x04 }, - { PMC_EV_ARMV7_DTLB_REFILL, 0x05 }, - { PMC_EV_ARMV7_MEM_READ, 0x06 }, - { PMC_EV_ARMV7_MEM_WRITE, 0x07 }, - { PMC_EV_ARMV7_INSTR_EXECUTED, 0x08 }, - { PMC_EV_ARMV7_EXC_TAKEN, 0x09 }, - { PMC_EV_ARMV7_EXC_EXECUTED, 0x0A }, - { PMC_EV_ARMV7_CID_WRITE, 0x0B }, - { PMC_EV_ARMV7_PC_WRITE, 0x0C }, - { PMC_EV_ARMV7_PC_IMM_BRANCH, 0x0D }, - { PMC_EV_ARMV7_PC_PROC_RETURN, 0x0E }, - { PMC_EV_ARMV7_MEM_UNALIGNED_ACCESS, 0x0F }, - { PMC_EV_ARMV7_PC_BRANCH_MIS_PRED, 0x10 }, - { PMC_EV_ARMV7_CLOCK_CYCLES, 0x11 }, - { PMC_EV_ARMV7_PC_BRANCH_PRED, 0x12 }, - { PMC_EV_ARMV7_MEM_ACCESS, 0x13 }, - { PMC_EV_ARMV7_L1_ICACHE_ACCESS, 0x14 }, - { PMC_EV_ARMV7_L1_DCACHE_WB, 0x15 }, - { PMC_EV_ARMV7_L2_CACHE_ACCESS, 0x16 }, - { PMC_EV_ARMV7_L2_CACHE_REFILL, 0x17 }, - { PMC_EV_ARMV7_L2_CACHE_WB, 0x18 }, - { PMC_EV_ARMV7_BUS_ACCESS, 0x19 }, - { PMC_EV_ARMV7_MEM_ERROR, 0x1A }, - { PMC_EV_ARMV7_INSTR_SPEC, 0x1B }, - { PMC_EV_ARMV7_TTBR_WRITE, 0x1C }, - { PMC_EV_ARMV7_BUS_CYCLES, 0x1D }, - { PMC_EV_ARMV7_CPU_CYCLES, 0xFF }, -}; - -const int armv7_event_codes_size = - sizeof(armv7_event_codes) / sizeof(armv7_event_codes[0]); - /* * Per-processor information. */ struct armv7_cpu { struct pmc_hw *pc_armv7pmcs; - int cortex_ver; }; static struct armv7_cpu **armv7_pcpu; @@ -173,10 +132,10 @@ static int armv7_allocate_pmc(int cpu, int ri, struct pmc *pm, const struct pmc_op_pmcallocate *a) { - uint32_t caps, config; struct armv7_cpu *pac; enum pmc_event pe; - int i; + uint32_t config; + uint32_t caps; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); @@ -190,18 +149,10 @@ armv7_allocate_pmc(int cpu, int ri, struct pmc *pm, return (EINVAL); pe = a->pm_ev; - for (i = 0; i < armv7_event_codes_size; i++) { - if (armv7_event_codes[i].pe_ev == pe) { - config = armv7_event_codes[i].pe_code; - break; - } - } - if (i == armv7_event_codes_size) - return EINVAL; - + config = (pe & EVENT_ID_MASK); pm->pm_md.pm_armv7.pm_armv7_evsel = config; - PMCDBG2(MDP,ALL,2,"armv7-allocate ri=%d -> config=0x%x", ri, config); + PMCDBG2(MDP, ALL, 2, "armv7-allocate ri=%d -> config=0x%x", ri, config); return 0; } @@ -225,7 +176,7 @@ armv7_read_pmc(int cpu, int ri, pmc_value_t *v) else tmp = armv7_pmcn_read(ri); - PMCDBG2(MDP,REA,2,"armv7-read id=%d -> %jd", ri, tmp); + PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) *v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); else @@ -249,7 +200,7 @@ armv7_write_pmc(int cpu, int ri, pmc_value_t v) if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) v = ARMV7_RELOAD_COUNT_TO_PERFCTR_VALUE(v); - PMCDBG3(MDP,WRI,1,"armv7-write cpu=%d ri=%d v=%jx", cpu, ri, v); + PMCDBG3(MDP, WRI, 1, "armv7-write cpu=%d ri=%d v=%jx", cpu, ri, v); if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) cp15_pmccntr_set(v); @@ -264,7 +215,7 @@ armv7_config_pmc(int cpu, int ri, struct pmc *pm) { struct pmc_hw *phw; - PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); + PMCDBG3(MDP, CFG, 1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); @@ -457,20 +408,15 @@ armv7_pcpu_init(struct pmc_mdep *md, int cpu) struct pmc_cpu *pc; uint32_t pmnc; int first_ri; - int cpuid; int i; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[armv7,%d] wrong cpu number %d", __LINE__, cpu)); - PMCDBG1(MDP,INI,1,"armv7-init cpu=%d", cpu); + PMCDBG1(MDP, INI, 1, "armv7-init cpu=%d", cpu); armv7_pcpu[cpu] = pac = malloc(sizeof(struct armv7_cpu), M_PMC, M_WAITOK|M_ZERO); - cpuid = cpu_ident(); - pac->cortex_ver = (cpuid >> CPU_ID_CORTEX_VER_SHIFT) & \ - CPU_ID_CORTEX_VER_MASK; - pac->pc_armv7pmcs = malloc(sizeof(struct pmc_hw) * armv7_npmcs, M_PMC, M_WAITOK|M_ZERO); pc = pmc_pcpu[cpu]; @@ -509,14 +455,15 @@ pmc_armv7_initialize() { struct pmc_mdep *pmc_mdep; struct pmc_classdep *pcd; + int idcode; int reg; reg = cp15_pmcr_get(); - armv7_npmcs = (reg >> ARMV7_PMNC_N_SHIFT) & \ ARMV7_PMNC_N_MASK; + idcode = (reg & ARMV7_IDCODE_MASK) >> ARMV7_IDCODE_SHIFT; - PMCDBG1(MDP,INI,1,"armv7-init npmcs=%d", armv7_npmcs); + PMCDBG1(MDP, INI, 1, "armv7-init npmcs=%d", armv7_npmcs); /* * Allocate space for pointers to PMC HW descriptors and for @@ -527,7 +474,20 @@ pmc_armv7_initialize() /* Just one class */ pmc_mdep = pmc_mdep_alloc(1); - pmc_mdep->pmd_cputype = PMC_CPU_ARMV7; + + switch (idcode) { + case ARMV7_IDCODE_CORTEX_A9: + pmc_mdep->pmd_cputype = PMC_CPU_ARMV7_CORTEX_A9; + break; + default: + case ARMV7_IDCODE_CORTEX_A8: + /* + * On A8 we implemented common events only, + * so use it for the rest of machines. + */ + pmc_mdep->pmd_cputype = PMC_CPU_ARMV7_CORTEX_A8; + break; + } pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_ARMV7]; pcd->pcd_caps = ARMV7_PMC_CAPS; diff --git a/sys/dev/hwpmc/hwpmc_armv7.h b/sys/dev/hwpmc/hwpmc_armv7.h index 35f7d5b..5282345f 100644 --- a/sys/dev/hwpmc/hwpmc_armv7.h +++ b/sys/dev/hwpmc/hwpmc_armv7.h @@ -48,9 +48,14 @@ #define ARMV7_PMNC_N_SHIFT 11 /* Number of counters implemented */ #define ARMV7_PMNC_N_MASK 0x1f #define ARMV7_PMNC_MASK 0x3f /* Writable bits */ +#define ARMV7_IDCODE_SHIFT 16 /* Identification code */ +#define ARMV7_IDCODE_MASK (0xff << ARMV7_IDCODE_SHIFT) +#define ARMV7_IDCODE_CORTEX_A9 9 +#define ARMV7_IDCODE_CORTEX_A8 8 #define ARMV7_RELOAD_COUNT_TO_PERFCTR_VALUE(R) (-(R)) #define ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P)) +#define EVENT_ID_MASK 0xFF #ifdef _KERNEL /* MD extension for 'struct pmc' */ diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h index 467367f..96dc900 100644 --- a/sys/dev/hwpmc/pmc_events.h +++ b/sys/dev/hwpmc/pmc_events.h @@ -4766,41 +4766,342 @@ __PMC_EV_ALIAS("IMPC_C0H_TRK_REQUEST.ALL", UCP_EVENT_84H_01H) * ARMv7 Events */ -#define __PMC_EV_ARMV7() \ - __PMC_EV(ARMV7, PMNC_SW_INCR) \ - __PMC_EV(ARMV7, L1_ICACHE_REFILL) \ - __PMC_EV(ARMV7, ITLB_REFILL) \ - __PMC_EV(ARMV7, L1_DCACHE_REFILL) \ - __PMC_EV(ARMV7, L1_DCACHE_ACCESS) \ - __PMC_EV(ARMV7, DTLB_REFILL) \ - __PMC_EV(ARMV7, MEM_READ) \ - __PMC_EV(ARMV7, MEM_WRITE) \ - __PMC_EV(ARMV7, INSTR_EXECUTED) \ - __PMC_EV(ARMV7, EXC_TAKEN) \ - __PMC_EV(ARMV7, EXC_EXECUTED) \ - __PMC_EV(ARMV7, CID_WRITE) \ - __PMC_EV(ARMV7, PC_WRITE) \ - __PMC_EV(ARMV7, PC_IMM_BRANCH) \ - __PMC_EV(ARMV7, PC_PROC_RETURN) \ - __PMC_EV(ARMV7, MEM_UNALIGNED_ACCESS) \ - __PMC_EV(ARMV7, PC_BRANCH_MIS_PRED) \ - __PMC_EV(ARMV7, CLOCK_CYCLES) \ - __PMC_EV(ARMV7, PC_BRANCH_PRED) \ - __PMC_EV(ARMV7, MEM_ACCESS) \ - __PMC_EV(ARMV7, L1_ICACHE_ACCESS) \ - __PMC_EV(ARMV7, L1_DCACHE_WB) \ - __PMC_EV(ARMV7, L2_CACHE_ACCESS) \ - __PMC_EV(ARMV7, L2_CACHE_REFILL) \ - __PMC_EV(ARMV7, L2_CACHE_WB) \ - __PMC_EV(ARMV7, BUS_ACCESS) \ - __PMC_EV(ARMV7, MEM_ERROR) \ - __PMC_EV(ARMV7, INSTR_SPEC) \ - __PMC_EV(ARMV7, TTBR_WRITE) \ - __PMC_EV(ARMV7, BUS_CYCLES) \ - __PMC_EV(ARMV7, CPU_CYCLES) +#define __PMC_EV_ARMV7() \ + __PMC_EV(ARMV7, EVENT_00H) \ + __PMC_EV(ARMV7, EVENT_01H) \ + __PMC_EV(ARMV7, EVENT_02H) \ + __PMC_EV(ARMV7, EVENT_03H) \ + __PMC_EV(ARMV7, EVENT_04H) \ + __PMC_EV(ARMV7, EVENT_05H) \ + __PMC_EV(ARMV7, EVENT_06H) \ + __PMC_EV(ARMV7, EVENT_07H) \ + __PMC_EV(ARMV7, EVENT_08H) \ + __PMC_EV(ARMV7, EVENT_09H) \ + __PMC_EV(ARMV7, EVENT_0AH) \ + __PMC_EV(ARMV7, EVENT_0BH) \ + __PMC_EV(ARMV7, EVENT_0CH) \ + __PMC_EV(ARMV7, EVENT_0DH) \ + __PMC_EV(ARMV7, EVENT_0EH) \ + __PMC_EV(ARMV7, EVENT_0FH) \ + __PMC_EV(ARMV7, EVENT_10H) \ + __PMC_EV(ARMV7, EVENT_11H) \ + __PMC_EV(ARMV7, EVENT_12H) \ + __PMC_EV(ARMV7, EVENT_13H) \ + __PMC_EV(ARMV7, EVENT_14H) \ + __PMC_EV(ARMV7, EVENT_15H) \ + __PMC_EV(ARMV7, EVENT_16H) \ + __PMC_EV(ARMV7, EVENT_17H) \ + __PMC_EV(ARMV7, EVENT_18H) \ + __PMC_EV(ARMV7, EVENT_19H) \ + __PMC_EV(ARMV7, EVENT_1AH) \ + __PMC_EV(ARMV7, EVENT_1BH) \ + __PMC_EV(ARMV7, EVENT_1CH) \ + __PMC_EV(ARMV7, EVENT_1DH) \ + __PMC_EV(ARMV7, EVENT_1EH) \ + __PMC_EV(ARMV7, EVENT_1FH) \ + __PMC_EV(ARMV7, EVENT_20H) \ + __PMC_EV(ARMV7, EVENT_21H) \ + __PMC_EV(ARMV7, EVENT_22H) \ + __PMC_EV(ARMV7, EVENT_23H) \ + __PMC_EV(ARMV7, EVENT_24H) \ + __PMC_EV(ARMV7, EVENT_25H) \ + __PMC_EV(ARMV7, EVENT_26H) \ + __PMC_EV(ARMV7, EVENT_27H) \ + __PMC_EV(ARMV7, EVENT_28H) \ + __PMC_EV(ARMV7, EVENT_29H) \ + __PMC_EV(ARMV7, EVENT_2AH) \ + __PMC_EV(ARMV7, EVENT_2BH) \ + __PMC_EV(ARMV7, EVENT_2CH) \ + __PMC_EV(ARMV7, EVENT_2DH) \ + __PMC_EV(ARMV7, EVENT_2EH) \ + __PMC_EV(ARMV7, EVENT_2FH) \ + __PMC_EV(ARMV7, EVENT_30H) \ + __PMC_EV(ARMV7, EVENT_31H) \ + __PMC_EV(ARMV7, EVENT_32H) \ + __PMC_EV(ARMV7, EVENT_33H) \ + __PMC_EV(ARMV7, EVENT_34H) \ + __PMC_EV(ARMV7, EVENT_35H) \ + __PMC_EV(ARMV7, EVENT_36H) \ + __PMC_EV(ARMV7, EVENT_37H) \ + __PMC_EV(ARMV7, EVENT_38H) \ + __PMC_EV(ARMV7, EVENT_39H) \ + __PMC_EV(ARMV7, EVENT_3AH) \ + __PMC_EV(ARMV7, EVENT_3BH) \ + __PMC_EV(ARMV7, EVENT_3CH) \ + __PMC_EV(ARMV7, EVENT_3DH) \ + __PMC_EV(ARMV7, EVENT_3EH) \ + __PMC_EV(ARMV7, EVENT_3FH) \ + __PMC_EV(ARMV7, EVENT_40H) \ + __PMC_EV(ARMV7, EVENT_41H) \ + __PMC_EV(ARMV7, EVENT_42H) \ + __PMC_EV(ARMV7, EVENT_43H) \ + __PMC_EV(ARMV7, EVENT_44H) \ + __PMC_EV(ARMV7, EVENT_45H) \ + __PMC_EV(ARMV7, EVENT_46H) \ + __PMC_EV(ARMV7, EVENT_47H) \ + __PMC_EV(ARMV7, EVENT_48H) \ + __PMC_EV(ARMV7, EVENT_49H) \ + __PMC_EV(ARMV7, EVENT_4AH) \ + __PMC_EV(ARMV7, EVENT_4BH) \ + __PMC_EV(ARMV7, EVENT_4CH) \ + __PMC_EV(ARMV7, EVENT_4DH) \ + __PMC_EV(ARMV7, EVENT_4EH) \ + __PMC_EV(ARMV7, EVENT_4FH) \ + __PMC_EV(ARMV7, EVENT_50H) \ + __PMC_EV(ARMV7, EVENT_51H) \ + __PMC_EV(ARMV7, EVENT_52H) \ + __PMC_EV(ARMV7, EVENT_53H) \ + __PMC_EV(ARMV7, EVENT_54H) \ + __PMC_EV(ARMV7, EVENT_55H) \ + __PMC_EV(ARMV7, EVENT_56H) \ + __PMC_EV(ARMV7, EVENT_57H) \ + __PMC_EV(ARMV7, EVENT_58H) \ + __PMC_EV(ARMV7, EVENT_59H) \ + __PMC_EV(ARMV7, EVENT_5AH) \ + __PMC_EV(ARMV7, EVENT_5BH) \ + __PMC_EV(ARMV7, EVENT_5CH) \ + __PMC_EV(ARMV7, EVENT_5DH) \ + __PMC_EV(ARMV7, EVENT_5EH) \ + __PMC_EV(ARMV7, EVENT_5FH) \ + __PMC_EV(ARMV7, EVENT_60H) \ + __PMC_EV(ARMV7, EVENT_61H) \ + __PMC_EV(ARMV7, EVENT_62H) \ + __PMC_EV(ARMV7, EVENT_63H) \ + __PMC_EV(ARMV7, EVENT_64H) \ + __PMC_EV(ARMV7, EVENT_65H) \ + __PMC_EV(ARMV7, EVENT_66H) \ + __PMC_EV(ARMV7, EVENT_67H) \ + __PMC_EV(ARMV7, EVENT_68H) \ + __PMC_EV(ARMV7, EVENT_69H) \ + __PMC_EV(ARMV7, EVENT_6AH) \ + __PMC_EV(ARMV7, EVENT_6BH) \ + __PMC_EV(ARMV7, EVENT_6CH) \ + __PMC_EV(ARMV7, EVENT_6DH) \ + __PMC_EV(ARMV7, EVENT_6EH) \ + __PMC_EV(ARMV7, EVENT_6FH) \ + __PMC_EV(ARMV7, EVENT_70H) \ + __PMC_EV(ARMV7, EVENT_71H) \ + __PMC_EV(ARMV7, EVENT_72H) \ + __PMC_EV(ARMV7, EVENT_73H) \ + __PMC_EV(ARMV7, EVENT_74H) \ + __PMC_EV(ARMV7, EVENT_75H) \ + __PMC_EV(ARMV7, EVENT_76H) \ + __PMC_EV(ARMV7, EVENT_77H) \ + __PMC_EV(ARMV7, EVENT_78H) \ + __PMC_EV(ARMV7, EVENT_79H) \ + __PMC_EV(ARMV7, EVENT_7AH) \ + __PMC_EV(ARMV7, EVENT_7BH) \ + __PMC_EV(ARMV7, EVENT_7CH) \ + __PMC_EV(ARMV7, EVENT_7DH) \ + __PMC_EV(ARMV7, EVENT_7EH) \ + __PMC_EV(ARMV7, EVENT_7FH) \ + __PMC_EV(ARMV7, EVENT_80H) \ + __PMC_EV(ARMV7, EVENT_81H) \ + __PMC_EV(ARMV7, EVENT_82H) \ + __PMC_EV(ARMV7, EVENT_83H) \ + __PMC_EV(ARMV7, EVENT_84H) \ + __PMC_EV(ARMV7, EVENT_85H) \ + __PMC_EV(ARMV7, EVENT_86H) \ + __PMC_EV(ARMV7, EVENT_87H) \ + __PMC_EV(ARMV7, EVENT_88H) \ + __PMC_EV(ARMV7, EVENT_89H) \ + __PMC_EV(ARMV7, EVENT_8AH) \ + __PMC_EV(ARMV7, EVENT_8BH) \ + __PMC_EV(ARMV7, EVENT_8CH) \ + __PMC_EV(ARMV7, EVENT_8DH) \ + __PMC_EV(ARMV7, EVENT_8EH) \ + __PMC_EV(ARMV7, EVENT_8FH) \ + __PMC_EV(ARMV7, EVENT_90H) \ + __PMC_EV(ARMV7, EVENT_91H) \ + __PMC_EV(ARMV7, EVENT_92H) \ + __PMC_EV(ARMV7, EVENT_93H) \ + __PMC_EV(ARMV7, EVENT_94H) \ + __PMC_EV(ARMV7, EVENT_95H) \ + __PMC_EV(ARMV7, EVENT_96H) \ + __PMC_EV(ARMV7, EVENT_97H) \ + __PMC_EV(ARMV7, EVENT_98H) \ + __PMC_EV(ARMV7, EVENT_99H) \ + __PMC_EV(ARMV7, EVENT_9AH) \ + __PMC_EV(ARMV7, EVENT_9BH) \ + __PMC_EV(ARMV7, EVENT_9CH) \ + __PMC_EV(ARMV7, EVENT_9DH) \ + __PMC_EV(ARMV7, EVENT_9EH) \ + __PMC_EV(ARMV7, EVENT_9FH) \ + __PMC_EV(ARMV7, EVENT_A0H) \ + __PMC_EV(ARMV7, EVENT_A1H) \ + __PMC_EV(ARMV7, EVENT_A2H) \ + __PMC_EV(ARMV7, EVENT_A3H) \ + __PMC_EV(ARMV7, EVENT_A4H) \ + __PMC_EV(ARMV7, EVENT_A5H) \ + __PMC_EV(ARMV7, EVENT_A6H) \ + __PMC_EV(ARMV7, EVENT_A7H) \ + __PMC_EV(ARMV7, EVENT_A8H) \ + __PMC_EV(ARMV7, EVENT_A9H) \ + __PMC_EV(ARMV7, EVENT_AAH) \ + __PMC_EV(ARMV7, EVENT_ABH) \ + __PMC_EV(ARMV7, EVENT_ACH) \ + __PMC_EV(ARMV7, EVENT_ADH) \ + __PMC_EV(ARMV7, EVENT_AEH) \ + __PMC_EV(ARMV7, EVENT_AFH) \ + __PMC_EV(ARMV7, EVENT_B0H) \ + __PMC_EV(ARMV7, EVENT_B1H) \ + __PMC_EV(ARMV7, EVENT_B2H) \ + __PMC_EV(ARMV7, EVENT_B3H) \ + __PMC_EV(ARMV7, EVENT_B4H) \ + __PMC_EV(ARMV7, EVENT_B5H) \ + __PMC_EV(ARMV7, EVENT_B6H) \ + __PMC_EV(ARMV7, EVENT_B7H) \ + __PMC_EV(ARMV7, EVENT_B8H) \ + __PMC_EV(ARMV7, EVENT_B9H) \ + __PMC_EV(ARMV7, EVENT_BAH) \ + __PMC_EV(ARMV7, EVENT_BBH) \ + __PMC_EV(ARMV7, EVENT_BCH) \ + __PMC_EV(ARMV7, EVENT_BDH) \ + __PMC_EV(ARMV7, EVENT_BEH) \ + __PMC_EV(ARMV7, EVENT_BFH) \ + __PMC_EV(ARMV7, EVENT_C0H) \ + __PMC_EV(ARMV7, EVENT_C1H) \ + __PMC_EV(ARMV7, EVENT_C2H) \ + __PMC_EV(ARMV7, EVENT_C3H) \ + __PMC_EV(ARMV7, EVENT_C4H) \ + __PMC_EV(ARMV7, EVENT_C5H) \ + __PMC_EV(ARMV7, EVENT_C6H) \ + __PMC_EV(ARMV7, EVENT_C7H) \ + __PMC_EV(ARMV7, EVENT_C8H) \ + __PMC_EV(ARMV7, EVENT_C9H) \ + __PMC_EV(ARMV7, EVENT_CAH) \ + __PMC_EV(ARMV7, EVENT_CBH) \ + __PMC_EV(ARMV7, EVENT_CCH) \ + __PMC_EV(ARMV7, EVENT_CDH) \ + __PMC_EV(ARMV7, EVENT_CEH) \ + __PMC_EV(ARMV7, EVENT_CFH) \ + __PMC_EV(ARMV7, EVENT_D0H) \ + __PMC_EV(ARMV7, EVENT_D1H) \ + __PMC_EV(ARMV7, EVENT_D2H) \ + __PMC_EV(ARMV7, EVENT_D3H) \ + __PMC_EV(ARMV7, EVENT_D4H) \ + __PMC_EV(ARMV7, EVENT_D5H) \ + __PMC_EV(ARMV7, EVENT_D6H) \ + __PMC_EV(ARMV7, EVENT_D7H) \ + __PMC_EV(ARMV7, EVENT_D8H) \ + __PMC_EV(ARMV7, EVENT_D9H) \ + __PMC_EV(ARMV7, EVENT_DAH) \ + __PMC_EV(ARMV7, EVENT_DBH) \ + __PMC_EV(ARMV7, EVENT_DCH) \ + __PMC_EV(ARMV7, EVENT_DDH) \ + __PMC_EV(ARMV7, EVENT_DEH) \ + __PMC_EV(ARMV7, EVENT_DFH) \ + __PMC_EV(ARMV7, EVENT_E0H) \ + __PMC_EV(ARMV7, EVENT_E1H) \ + __PMC_EV(ARMV7, EVENT_E2H) \ + __PMC_EV(ARMV7, EVENT_E3H) \ + __PMC_EV(ARMV7, EVENT_E4H) \ + __PMC_EV(ARMV7, EVENT_E5H) \ + __PMC_EV(ARMV7, EVENT_E6H) \ + __PMC_EV(ARMV7, EVENT_E7H) \ + __PMC_EV(ARMV7, EVENT_E8H) \ + __PMC_EV(ARMV7, EVENT_E9H) \ + __PMC_EV(ARMV7, EVENT_EAH) \ + __PMC_EV(ARMV7, EVENT_EBH) \ + __PMC_EV(ARMV7, EVENT_ECH) \ + __PMC_EV(ARMV7, EVENT_EDH) \ + __PMC_EV(ARMV7, EVENT_EEH) \ + __PMC_EV(ARMV7, EVENT_EFH) \ + __PMC_EV(ARMV7, EVENT_F0H) \ + __PMC_EV(ARMV7, EVENT_F1H) \ + __PMC_EV(ARMV7, EVENT_F2H) \ + __PMC_EV(ARMV7, EVENT_F3H) \ + __PMC_EV(ARMV7, EVENT_F4H) \ + __PMC_EV(ARMV7, EVENT_F5H) \ + __PMC_EV(ARMV7, EVENT_F6H) \ + __PMC_EV(ARMV7, EVENT_F7H) \ + __PMC_EV(ARMV7, EVENT_F8H) \ + __PMC_EV(ARMV7, EVENT_F9H) \ + __PMC_EV(ARMV7, EVENT_FAH) \ + __PMC_EV(ARMV7, EVENT_FBH) \ + __PMC_EV(ARMV7, EVENT_FCH) \ + __PMC_EV(ARMV7, EVENT_FDH) \ + __PMC_EV(ARMV7, EVENT_FEH) \ + __PMC_EV(ARMV7, EVENT_FFH) -#define PMC_EV_ARMV7_FIRST PMC_EV_ARMV7_PMNC_SW_INCR -#define PMC_EV_ARMV7_LAST PMC_EV_ARMV7_CPU_CYCLES +#define PMC_EV_ARMV7_FIRST PMC_EV_ARMV7_EVENT_00H +#define PMC_EV_ARMV7_LAST PMC_EV_ARMV7_EVENT_FFH + +#define __PMC_EV_ALIAS_ARMV7_COMMON() \ + __PMC_EV_ALIAS("PMNC_SW_INCR", ARMV7_EVENT_00H) \ + __PMC_EV_ALIAS("L1_ICACHE_REFILL", ARMV7_EVENT_01H) \ + __PMC_EV_ALIAS("ITLB_REFILL", ARMV7_EVENT_02H) \ + __PMC_EV_ALIAS("L1_DCACHE_REFILL", ARMV7_EVENT_03H) \ + __PMC_EV_ALIAS("L1_DCACHE_ACCESS", ARMV7_EVENT_04H) \ + __PMC_EV_ALIAS("DTLB_REFILL", ARMV7_EVENT_05H) \ + __PMC_EV_ALIAS("MEM_READ", ARMV7_EVENT_06H) \ + __PMC_EV_ALIAS("MEM_WRITE", ARMV7_EVENT_07H) \ + __PMC_EV_ALIAS("INSTR_EXECUTED", ARMV7_EVENT_08H) \ + __PMC_EV_ALIAS("EXC_TAKEN", ARMV7_EVENT_09H) \ + __PMC_EV_ALIAS("EXC_EXECUTED", ARMV7_EVENT_0AH) \ + __PMC_EV_ALIAS("CID_WRITE", ARMV7_EVENT_0BH) \ + __PMC_EV_ALIAS("PC_WRITE", ARMV7_EVENT_0CH) \ + __PMC_EV_ALIAS("PC_IMM_BRANCH", ARMV7_EVENT_0DH) \ + __PMC_EV_ALIAS("PC_PROC_RETURN", ARMV7_EVENT_0EH) \ + __PMC_EV_ALIAS("MEM_UNALIGNED_ACCESS", ARMV7_EVENT_0FH) \ + __PMC_EV_ALIAS("PC_BRANCH_MIS_PRED", ARMV7_EVENT_10H) \ + __PMC_EV_ALIAS("CLOCK_CYCLES", ARMV7_EVENT_11H) \ + __PMC_EV_ALIAS("PC_BRANCH_PRED", ARMV7_EVENT_12H) \ + __PMC_EV_ALIAS("MEM_ACCESS", ARMV7_EVENT_13H) \ + __PMC_EV_ALIAS("L1_ICACHE_ACCESS", ARMV7_EVENT_14H) \ + __PMC_EV_ALIAS("L1_DCACHE_WB", ARMV7_EVENT_15H) \ + __PMC_EV_ALIAS("L2_CACHE_ACCESS", ARMV7_EVENT_16H) \ + __PMC_EV_ALIAS("L2_CACHE_REFILL", ARMV7_EVENT_17H) \ + __PMC_EV_ALIAS("L2_CACHE_WB", ARMV7_EVENT_18H) \ + __PMC_EV_ALIAS("BUS_ACCESS", ARMV7_EVENT_19H) \ + __PMC_EV_ALIAS("MEM_ERROR", ARMV7_EVENT_1AH) \ + __PMC_EV_ALIAS("INSTR_SPEC", ARMV7_EVENT_1BH) \ + __PMC_EV_ALIAS("TTBR_WRITE", ARMV7_EVENT_1CH) \ + __PMC_EV_ALIAS("BUS_CYCLES", ARMV7_EVENT_1DH) \ + __PMC_EV_ALIAS("CPU_CYCLES", ARMV7_EVENT_FFH) + +#define __PMC_EV_ALIAS_ARMV7_CORTEX_A8() \ + __PMC_EV_ALIAS_ARMV7_COMMON() + +#define __PMC_EV_ALIAS_ARMV7_CORTEX_A9() \ + __PMC_EV_ALIAS_ARMV7_COMMON() \ + __PMC_EV_ALIAS("JAVA_BYTECODE", ARMV7_EVENT_40H) \ + __PMC_EV_ALIAS("SOFTWARE_JAVA_BYTECODE", ARMV7_EVENT_41H) \ + __PMC_EV_ALIAS("JAZELLE_BACKWARD_BRANCH", ARMV7_EVENT_42H) \ + __PMC_EV_ALIAS("COHERENT_LINEFILL_MISSC", ARMV7_EVENT_50H) \ + __PMC_EV_ALIAS("COHERENT_LINEFILL_HITC", ARMV7_EVENT_51H) \ + __PMC_EV_ALIAS("INSTR_CACHE_DEPENDENT_STALL", ARMV7_EVENT_60H) \ + __PMC_EV_ALIAS("DATA_CACHE_DEPENDENT_STALL", ARMV7_EVENT_61H) \ + __PMC_EV_ALIAS("MAIN_TLB_MISS_STALL", ARMV7_EVENT_62H) \ + __PMC_EV_ALIAS("STREX_PASSED", ARMV7_EVENT_63H) \ + __PMC_EV_ALIAS("STREX_FAILED", ARMV7_EVENT_64H) \ + __PMC_EV_ALIAS("DATA_EVICTION", ARMV7_EVENT_65H) \ + __PMC_EV_ALIAS("ISSUE_DNOT_DISPATCH_ANY_INSTR", ARMV7_EVENT_66H) \ + __PMC_EV_ALIAS("ISSUE_IS_EMPTY", ARMV7_EVENT_67H) \ + __PMC_EV_ALIAS("MAIN_EXECUTION_UNIT_PIPE", ARMV7_EVENT_70H) \ + __PMC_EV_ALIAS("SECOND_EXECUTION_UNIT_PIPE", ARMV7_EVENT_71H) \ + __PMC_EV_ALIAS("LOAD_STORE_PIPE", ARMV7_EVENT_72H) \ + __PMC_EV_ALIAS("FLOATING_POINT_INSTR_RENAMED", ARMV7_EVENT_73H) \ + __PMC_EV_ALIAS("NEON_INSTRS_RENAMED", ARMV7_EVENT_74H) \ + __PMC_EV_ALIAS("PLD_STALL", ARMV7_EVENT_80H) \ + __PMC_EV_ALIAS("WRITE_STALL", ARMV7_EVENT_81H) \ + __PMC_EV_ALIAS("INSTR_MAIN_TLB_MISS_STALL", ARMV7_EVENT_82H) \ + __PMC_EV_ALIAS("DATA_MAIN_TLB_MISS_STALL", ARMV7_EVENT_83H) \ + __PMC_EV_ALIAS("INSTR_MICRO_TLB_MISS_STALL", ARMV7_EVENT_84H) \ + __PMC_EV_ALIAS("DATA_MICRO_TLB_MISS_STALL", ARMV7_EVENT_85H) \ + __PMC_EV_ALIAS("DMB_STALL", ARMV7_EVENT_86H) \ + __PMC_EV_ALIAS("INTEGER_CORE_CLOCK_ENABLED", ARMV7_EVENT_8AH) \ + __PMC_EV_ALIAS("DATA_ENGINE_CLOCK_ENABLED", ARMV7_EVENT_8BH) \ + __PMC_EV_ALIAS("ISB", ARMV7_EVENT_90H) \ + __PMC_EV_ALIAS("DSB", ARMV7_EVENT_91H) \ + __PMC_EV_ALIAS("DMB", ARMV7_EVENT_92H) \ + __PMC_EV_ALIAS("EXTERNAL_INTERRUPT", ARMV7_EVENT_93H) \ + __PMC_EV_ALIAS("PLE_CACHE_LINE_REQ_COMPLETED", ARMV7_EVENT_A0H) \ + __PMC_EV_ALIAS("PLE_CACHE_LINE_REQ_SKIPPED", ARMV7_EVENT_A1H) \ + __PMC_EV_ALIAS("PLE_FIFO_FLUSH", ARMV7_EVENT_A2H) \ + __PMC_EV_ALIAS("PLE_REQUEST_COMPLETED", ARMV7_EVENT_A3H) \ + __PMC_EV_ALIAS("PLE_FIFO_OVERFLOW", ARMV7_EVENT_A4H) \ + __PMC_EV_ALIAS("PLE_REQUEST_PROGRAMMED", ARMV7_EVENT_A5H) /* * ARMv8 Events diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index ae8b179..00ba2c3 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -5,7 +5,7 @@ * Copyright (c) 2000 Whistle Communications, Inc. * All rights reserved. * Author: Archie Cobbs <archie@freebsd.org> - * + * * Subject to the following obligations and disclaimer of warranty, use and * redistribution of this software, in source or object code forms, with or * without modifications are expressly permitted by Whistle Communications; @@ -16,7 +16,7 @@ * Communications, Inc. trademarks, including the mark "WHISTLE * COMMUNICATIONS" on advertising, endorsements, or otherwise except as * such appears in the above copyright notice or in the software. - * + * * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, @@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$"); #define ID_LPTLP 0x9c228086 #define ID_WCPT 0x8ca28086 #define ID_WCPTLP 0x9ca28086 +#define ID_WELLSBURG 0x8d228086 #define PCIS_SERIALBUS_SMBUS_PROGIF 0x00 @@ -212,6 +213,9 @@ ichsmb_pci_probe(device_t dev) case ID_COLETOCRK: device_set_desc(dev, "Intel Coleto Creek SMBus controller"); break; + case ID_WELLSBURG: + device_set_desc(dev, "Intel Wellsburg SMBus controller"); + break; default: return (ENXIO); } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 881f58a..46edd3e 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -2931,6 +2931,14 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) atp = isp_find_atpd(isp, tptr, ((ct_entry_t *)arg)->ct_fwhandle); } if (atp == NULL) { + /* + * In case of target mode disable at least ISP2532 return + * invalid zero ct_rxid value. Try to workaround that using + * tag_id from the CCB, pointed by valid ct_syshandle. + */ + atp = isp_find_atpd(isp, tptr, ccb->csio.tag_id); + } + if (atp == NULL) { rls_lun_statep(isp, tptr); isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ccb->csio.tag_id); return; diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index a04d446..f3cf2ae 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -232,6 +232,7 @@ static int iwn_tx_data(struct iwn_softc *, struct mbuf *, static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *, struct ieee80211_node *, const struct ieee80211_bpf_params *params); +static void iwn_xmit_task(void *arg0, int pending); static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void iwn_start(struct ifnet *); @@ -682,6 +683,9 @@ iwn_attach(device_t dev) TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc); TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc); + TASK_INIT(&sc->sc_xmit_task, 0, iwn_xmit_task, sc); + + mbufq_init(&sc->sc_xmit_queue, 1024); sc->sc_tq = taskqueue_create("iwn_taskq", M_WAITOK, taskqueue_thread_enqueue, &sc->sc_tq); @@ -1360,6 +1364,28 @@ iwn_vap_delete(struct ieee80211vap *vap) free(ivp, M_80211_VAP); } +static void +iwn_xmit_queue_drain(struct iwn_softc *sc) +{ + struct mbuf *m; + struct ieee80211_node *ni; + + IWN_LOCK_ASSERT(sc); + while ((m = mbufq_dequeue(&sc->sc_xmit_queue)) != NULL) { + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + ieee80211_free_node(ni); + m_freem(m); + } +} + +static int +iwn_xmit_queue_enqueue(struct iwn_softc *sc, struct mbuf *m) +{ + + IWN_LOCK_ASSERT(sc); + return (mbufq_enqueue(&sc->sc_xmit_queue, m)); +} + static int iwn_detach(device_t dev) { @@ -1373,6 +1399,11 @@ iwn_detach(device_t dev) if (ifp != NULL) { ic = ifp->if_l2com; + /* Free the mbuf queue and node references */ + IWN_LOCK(sc); + iwn_xmit_queue_drain(sc); + IWN_UNLOCK(sc); + ieee80211_draintask(ic, &sc->sc_reinit_task); ieee80211_draintask(ic, &sc->sc_radioon_task); ieee80211_draintask(ic, &sc->sc_radiooff_task); @@ -2831,6 +2862,9 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->rxon->filter &= ~htole32(IWN_FILTER_BSS); sc->calib.state = IWN_CALIB_STATE_INIT; + /* Wait until we hear a beacon before we transmit */ + sc->sc_beacon_wait = 1; + if ((error = iwn_auth(sc, vap)) != 0) { device_printf(sc->sc_dev, "%s: could not move to auth state\n", __func__); @@ -2846,6 +2880,9 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) break; } + /* Wait until we hear a beacon before we transmit */ + sc->sc_beacon_wait = 1; + /* * !RUN -> RUN requires setting the association id * which is done with a firmware cmd. We also defer @@ -2859,6 +2896,12 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) case IEEE80211_S_INIT: sc->calib.state = IWN_CALIB_STATE_INIT; + /* + * Purge the xmit queue so we don't have old frames + * during a new association attempt. + */ + sc->sc_beacon_wait = 0; + iwn_xmit_queue_drain(sc); break; default: @@ -3066,6 +3109,32 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, } } + /* + * If it's a beacon and we're waiting, then do the + * wakeup. This should unblock raw_xmit/start. + */ + if (sc->sc_beacon_wait) { + uint8_t type, subtype; + /* NB: Re-assign wh */ + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + /* + * This assumes at this point we've received our own + * beacon. + */ + DPRINTF(sc, IWN_DEBUG_TRACE, + "%s: beacon_wait, type=%d, subtype=%d\n", + __func__, type, subtype); + if (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_BEACON) { + DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, + "%s: waking things up\n", __func__); + /* queue taskqueue to transmit! */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_xmit_task); + } + } + IWN_UNLOCK(sc); /* Send the frame to the 802.11 layer. */ @@ -4802,6 +4871,51 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, return 0; } +static void +iwn_xmit_task(void *arg0, int pending) +{ + struct iwn_softc *sc = arg0; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211_node *ni; + struct mbuf *m; + int error; + struct ieee80211_bpf_params p; + int have_p; + + DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__); + + IWN_LOCK(sc); + /* + * Dequeue frames, attempt to transmit, + * then disable beaconwait when we're done. + */ + while ((m = mbufq_dequeue(&sc->sc_xmit_queue)) != NULL) { + have_p = 0; + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + + /* Get xmit params if appropriate */ + if (ieee80211_get_xmit_params(m, &p) == 0) + have_p = 1; + + DPRINTF(sc, IWN_DEBUG_XMIT, "%s: m=%p, have_p=%d\n", + __func__, m, have_p); + + /* If we have xmit params, use them */ + if (have_p) + error = iwn_tx_data_raw(sc, m, ni, &p); + else + error = iwn_tx_data(sc, m, ni); + + if (error != 0) { + ieee80211_free_node(ni); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + } + } + + sc->sc_beacon_wait = 0; + IWN_UNLOCK(sc); +} + static int iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) @@ -4819,7 +4933,25 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return ENETDOWN; } + /* XXX? net80211 doesn't set this on xmit'ed raw frames? */ + m->m_pkthdr.rcvif = (void *) ni; + IWN_LOCK(sc); + + /* queue frame if we have to */ + if (sc->sc_beacon_wait) { + if (iwn_xmit_queue_enqueue(sc, m) != 0) { + m_freem(m); + ieee80211_free_node(ni); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + IWN_UNLOCK(sc); + return (ENOBUFS); + } + /* Queued, so just return OK */ + IWN_UNLOCK(sc); + return (0); + } + if (params == NULL) { /* * Legacy path; interpret frame contents to decide @@ -4866,6 +4998,14 @@ iwn_start_locked(struct ifnet *ifp) IWN_LOCK_ASSERT(sc); + /* + * If we're waiting for a beacon, we can just exit out here + * and wait for the taskqueue to be kicked. + */ + if (sc->sc_beacon_wait) { + return; + } + DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h index b14158b..9366fc2 100644 --- a/sys/dev/iwn/if_iwnvar.h +++ b/sys/dev/iwn/if_iwnvar.h @@ -309,6 +309,7 @@ struct iwn_softc { struct task sc_radioon_task; struct task sc_radiooff_task; struct task sc_panic_task; + struct task sc_xmit_task; /* Taskqueue */ struct taskqueue *sc_tq; @@ -385,6 +386,9 @@ struct iwn_softc { /* Are we doing a scan? */ int sc_is_scanning; + /* Are we waiting for a beacon before xmit? */ + int sc_beacon_wait; + struct ieee80211_tx_ampdu *qid2tap[IWN5000_NTXQUEUES]; int (*sc_ampdu_rx_start)(struct ieee80211_node *, @@ -417,6 +421,13 @@ struct iwn_softc { #define IWN_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) uint32_t ucode_rev; + + /* + * Global queue for queuing xmit frames + * when we can't yet transmit (eg raw + * frames whilst waiting for beacons.) + */ + struct mbufq sc_xmit_queue; }; #define IWN_LOCK_INIT(_sc) \ diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index 13a678c..1a36c2a 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -2551,7 +2551,7 @@ ixl_setup_interface(device_t dev, struct ixl_vsi *vsi) } if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = ETHERMTU; - ifp->if_baudrate = 4000000000; // ?? + ifp->if_baudrate = IF_Gbps(40); ifp->if_init = ixl_init; ifp->if_softc = vsi; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; diff --git a/sys/dev/mii/mii.h b/sys/dev/mii/mii.h index 668fb8f..fa1ec84 100644 --- a/sys/dev/mii/mii.h +++ b/sys/dev/mii/mii.h @@ -1,4 +1,4 @@ -/* $NetBSD: mii.h,v 1.9 2001/05/31 03:07:14 thorpej Exp $ */ +/* $NetBSD: mii.h,v 1.18 2014/06/16 14:43:22 msaitoh Exp $ */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. @@ -87,7 +87,7 @@ /* * Note that the EXTSTAT bit indicates that there is extended status * info available in register 15, but 802.3 section 22.2.4.3 also - * states that that all 1000 Mb/s capable PHYs will set this bit to 1. + * states that all 1000 Mb/s capable PHYs will set this bit to 1. */ #define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX| \ @@ -111,6 +111,7 @@ #define ANAR_NP 0x8000 /* Next page (ro) */ #define ANAR_ACK 0x4000 /* link partner abilities acknowledged (ro) */ #define ANAR_RF 0x2000 /* remote fault (ro) */ + /* Annex 28B.2 */ #define ANAR_FC 0x0400 /* local device supports PAUSE */ #define ANAR_T4 0x0200 /* local device supports 100bT4 */ #define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */ @@ -123,6 +124,7 @@ #define ANAR_PAUSE_ASYM (2 << 10) #define ANAR_PAUSE_TOWARDS (3 << 10) + /* Annex 28D */ #define ANAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */ #define ANAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */ #define ANAR_X_PAUSE_NONE (0 << 7) @@ -184,12 +186,47 @@ #define GTSR_MAN_MS_FLT 0x8000 /* master/slave config fault */ #define GTSR_MS_RES 0x4000 /* result: 1 = master, 0 = slave */ #define GTSR_LRS 0x2000 /* local rx status, 1 = ok */ -#define GTSR_RRS 0x1000 /* remove rx status, 1 = ok */ +#define GTSR_RRS 0x1000 /* remote rx status, 1 = ok */ #define GTSR_LP_1000TFDX 0x0800 /* link partner 1000baseT FDX capable */ #define GTSR_LP_1000THDX 0x0400 /* link partner 1000baseT HDX capable */ #define GTSR_LP_ASM_DIR 0x0200 /* link partner asym. pause dir. capable */ #define GTSR_IDLE_ERR 0x00ff /* IDLE error count */ +#define MII_PSECR 0x0b /* PSE control register */ +#define PSECR_PACTLMASK 0x000c /* pair control mask */ +#define PSECR_PSEENMASK 0x0003 /* PSE enable mask */ +#define PSECR_PINOUTB 0x0008 /* PSE pinout Alternative B */ +#define PSECR_PINOUTA 0x0004 /* PSE pinout Alternative A */ +#define PSECR_FOPOWTST 0x0002 /* Force Power Test Mode */ +#define PSECR_PSEEN 0x0001 /* PSE Enabled */ +#define PSECR_PSEDIS 0x0000 /* PSE Disabled */ + +#define MII_PSESR 0x0c /* PSE status register */ +#define PSESR_PWRDENIED 0x1000 /* Power Denied */ +#define PSESR_VALSIG 0x0800 /* Valid PD signature detected */ +#define PSESR_INVALSIG 0x0400 /* Invalid PD signature detected */ +#define PSESR_SHORTCIRC 0x0200 /* Short circuit condition detected */ +#define PSESR_OVERLOAD 0x0100 /* Overload condition detected */ +#define PSESR_MPSABSENT 0x0080 /* MPS absent condition detected */ +#define PSESR_PDCLMASK 0x0070 /* PD Class mask */ +#define PSESR_STATMASK 0x000e /* PSE Status mask */ +#define PSESR_PAIRCTABL 0x0001 /* PAIR Control Ability */ +#define PSESR_PDCL_4 (4 << 4) /* Class 4 */ +#define PSESR_PDCL_3 (3 << 4) /* Class 3 */ +#define PSESR_PDCL_2 (2 << 4) /* Class 2 */ +#define PSESR_PDCL_1 (1 << 4) /* Class 1 */ +#define PSESR_PDCL_0 (0 << 4) /* Class 0 */ + +#define MII_MMDACR 0x0d /* MMD access control register */ +#define MMDACR_FUNCMASK 0xc000 /* function */ +#define MMDACR_DADDRMASK 0x001f /* device address */ +#define MMDACR_FN_ADDRESS (0 << 14) /* address */ +#define MMDACR_FN_DATANPI (1 << 14) /* data, no post increment */ +#define MMDACR_FN_DATAPIRW (2 << 14) /* data, post increment on r/w */ +#define MMDACR_FN_DATAPIW (3 << 14) /* data, post increment on wr only */ + +#define MII_MMDAADR 0x0e /* MMD access address data register */ + #define MII_EXTSR 0x0f /* Extended status register */ #define EXTSR_1000XFDX 0x8000 /* 1000X full-duplex capable */ #define EXTSR_1000XHDX 0x4000 /* 1000X half-duplex capable */ diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index a9261ce..233675d 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -551,3 +551,44 @@ ofw_bus_find_compatible(phandle_t node, const char *onecompat) } return (0); } + +/** + * @brief Return child of bus whose phandle is node + * + * A direct child of @p will be returned if it its phandle in the + * OFW tree is @p node. Otherwise, NULL is returned. + * + * @param bus The bus to examine + * @param node The phandle_t to look for. + */ +device_t +ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node) +{ + device_t *children, retval, child; + int nkid, i; + + /* + * Nothing can match the flag value for no node. + */ + if (node == -1) + return (NULL); + + /* + * Search the children for a match. We microoptimize + * a bit by not using ofw_bus_get since we already know + * the parent. We do not recurse. + */ + if (device_get_children(bus, &children, &nkid) != 0) + return (NULL); + retval = NULL; + for (i = 0; i < nkid; i++) { + child = children[i]; + if (OFW_BUS_GET_NODE(bus, child) == node) { + retval = child; + break; + } + } + free(children, M_TEMP); + + return (retval); +} diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index bbeda7f..c59a75d 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -107,4 +107,7 @@ phandle_t ofw_bus_find_compatible(phandle_t, const char *); /* Helper to search for a child with a given name */ phandle_t ofw_bus_find_child(phandle_t, const char *); +/* Helper routine to find a device_t child matchig a given phandle_t */ +device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node); + #endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */ diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c new file mode 100644 index 0000000..04dc8d3 --- /dev/null +++ b/sys/dev/pci/pci_host_generic.c @@ -0,0 +1,626 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of 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. + */ + +/* Generic ECAM PCIe driver */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/rman.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/endian.h> +#include <sys/cpuset.h> +#include <sys/rwlock.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcib_private.h> +#include <machine/cpu.h> +#include <machine/bus.h> +#include <machine/intr.h> +#include <vm/vm_page.h> + +#include "pcib_if.h" + +/* Assembling ECAM Configuration Address */ +#define PCIE_BUS_SHIFT 20 +#define PCIE_SLOT_SHIFT 15 +#define PCIE_FUNC_SHIFT 12 +#define PCIE_BUS_MASK 0xFF +#define PCIE_SLOT_MASK 0x1F +#define PCIE_FUNC_MASK 0x07 +#define PCIE_REG_MASK 0xFFF + +#define PCIE_ADDR_OFFSET(bus, slot, func, reg) \ + ((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT) | \ + (((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT) | \ + (((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT) | \ + ((reg) & PCIE_REG_MASK)) + +#define MAX_RANGES_TUPLES 5 +#define MIN_RANGES_TUPLES 2 + +#define PCI_IO_WINDOW_OFFSET 0x1000 +#define PCI_IRQ_START 32 +#define PCI_IRQ_END (PCI_IRQ_START + 4) + +#define SPACE_CODE_SHIFT 24 +#define SPACE_CODE_MASK 0x3 +#define SPACE_CODE_IO_SPACE 0x1 +#define PROPS_CELL_SIZE 1 +#define PCI_ADDR_CELL_SIZE 2 + +struct pcie_range { + uint64_t pci_base; + uint64_t phys_base; + uint64_t size; + uint64_t flags; +#define FLAG_IO (1 << 0) +#define FLAG_MEM (1 << 1) +}; + +struct generic_pcie_softc { + struct pcie_range ranges[MAX_RANGES_TUPLES]; + int nranges; + struct rman mem_rman; + struct rman io_rman; + struct rman irq_rman; + struct resource *res; + struct resource *res1; + int ecam; + bus_space_tag_t bst; + bus_space_handle_t bsh; + device_t dev; + bus_space_handle_t ioh; +}; + +/* Forward prototypes */ + +static int generic_pcie_probe(device_t dev); +static int generic_pcie_attach(device_t dev); +static int parse_pci_mem_ranges(struct generic_pcie_softc *sc); +static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot, + u_int func, u_int reg, int bytes); +static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot, + u_int func, u_int reg, uint32_t val, int bytes); +static int generic_pcie_maxslots(device_t dev); +static int generic_pcie_read_ivar(device_t dev, device_t child, int index, + uintptr_t *result); +static int generic_pcie_write_ivar(device_t dev, device_t child, int index, + uintptr_t value); +static struct resource *generic_pcie_alloc_resource(device_t dev, + device_t child, int type, int *rid, u_long start, u_long end, + u_long count, u_int flags); +static int generic_pcie_release_resource(device_t dev, device_t child, + int type, int rid, struct resource *res); + +static int +generic_pcie_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) { + device_set_desc(dev, "Generic PCI host controller"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +generic_pcie_attach(device_t dev) +{ + struct generic_pcie_softc *sc; + uint64_t phys_base; + uint64_t pci_base; + uint64_t size; + int error; + int tuple; + int rid; + + sc = device_get_softc(dev); + sc->dev = dev; + + rid = 0; + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "could not map memory.\n"); + return (ENXIO); + } + + sc->bst = rman_get_bustag(sc->res); + sc->bsh = rman_get_bushandle(sc->res); + + sc->mem_rman.rm_type = RMAN_ARRAY; + sc->mem_rman.rm_descr = "PCIe Memory"; + sc->io_rman.rm_type = RMAN_ARRAY; + sc->io_rman.rm_descr = "PCIe IO window"; + + /* Retrieve 'ranges' property from FDT */ + if (bootverbose) + device_printf(dev, "parsing FDT for ECAM%d:\n", + sc->ecam); + if (parse_pci_mem_ranges(sc)) + return (ENXIO); + + /* Initialize rman and allocate memory regions */ + error = rman_init(&sc->mem_rman); + if (error) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + return (error); + } + + error = rman_init(&sc->io_rman); + if (error) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + return (error); + } + + for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { + phys_base = sc->ranges[tuple].phys_base; + pci_base = sc->ranges[tuple].pci_base; + size = sc->ranges[tuple].size; + if (phys_base == 0 || size == 0) + continue; /* empty range element */ + if (sc->ranges[tuple].flags & FLAG_MEM) { + error = rman_manage_region(&sc->mem_rman, + phys_base, + phys_base + size); + } else if (sc->ranges[tuple].flags & FLAG_IO) { + error = rman_manage_region(&sc->io_rman, + pci_base + PCI_IO_WINDOW_OFFSET, + pci_base + PCI_IO_WINDOW_OFFSET + size); + } else + continue; + if (error) { + device_printf(dev, "rman_manage_region() failed." + "error = %d\n", error); + rman_fini(&sc->mem_rman); + return (error); + } + } + + /* TODO: get IRQ numbers from FDT */ + sc->irq_rman.rm_type = RMAN_ARRAY; + sc->irq_rman.rm_descr = "Generic PCIe IRQs"; + if (rman_init(&sc->irq_rman) != 0 || + rman_manage_region(&sc->irq_rman, PCI_IRQ_START, + PCI_IRQ_END) != 0) { + panic("Generic PCI: failed to set up IRQ rman"); + } + + device_add_child(dev, "pci", -1); + return (bus_generic_attach(dev)); +} + +static int +parse_pci_mem_ranges(struct generic_pcie_softc *sc) +{ + pcell_t pci_addr_cells, parent_addr_cells; + pcell_t attributes, size_cells; + cell_t *base_ranges; + int nbase_ranges; + phandle_t node; + int i, j, k; + int tuple; + + node = ofw_bus_get_node(sc->dev); + + OF_getencprop(node, "#address-cells", &pci_addr_cells, + sizeof(pci_addr_cells)); + OF_getencprop(node, "#size-cells", &size_cells, + sizeof(size_cells)); + OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells, + sizeof(parent_addr_cells)); + + if (parent_addr_cells != 2 || pci_addr_cells != 3 || size_cells != 2) { + device_printf(sc->dev, + "Unexpected number of address or size cells in FDT\n"); + return (ENXIO); + } + + nbase_ranges = OF_getproplen(node, "ranges"); + sc->nranges = nbase_ranges / sizeof(cell_t) / + (parent_addr_cells + pci_addr_cells + size_cells); + base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); + OF_getencprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < sc->nranges; i++) { + attributes = (base_ranges[j++] >> SPACE_CODE_SHIFT) & \ + SPACE_CODE_MASK; + if (attributes == SPACE_CODE_IO_SPACE) { + sc->ranges[i].flags |= FLAG_IO; + } else { + sc->ranges[i].flags |= FLAG_MEM; + } + + sc->ranges[i].pci_base = 0; + for (k = 0; k < (pci_addr_cells - 1); k++) { + sc->ranges[i].pci_base <<= 32; + sc->ranges[i].pci_base |= base_ranges[j++]; + } + sc->ranges[i].phys_base = 0; + for (k = 0; k < parent_addr_cells; k++) { + sc->ranges[i].phys_base <<= 32; + sc->ranges[i].phys_base |= base_ranges[j++]; + } + sc->ranges[i].size = 0; + for (k = 0; k < size_cells; k++) { + sc->ranges[i].size <<= 32; + sc->ranges[i].size |= base_ranges[j++]; + } + } + + for (; i < MAX_RANGES_TUPLES; i++) { + /* zero-fill remaining tuples to mark empty elements in array */ + sc->ranges[i].pci_base = 0; + sc->ranges[i].phys_base = 0; + sc->ranges[i].size = 0; + } + + if (bootverbose) { + for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { + device_printf(sc->dev, + "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n", + sc->ranges[tuple].pci_base, + sc->ranges[tuple].phys_base, + sc->ranges[tuple].size); + } + } + + free(base_ranges, M_DEVBUF); + return (0); +} + +static uint32_t +generic_pcie_read_config(device_t dev, u_int bus, u_int slot, + u_int func, u_int reg, int bytes) +{ + struct generic_pcie_softc *sc; + bus_space_handle_t h; + bus_space_tag_t t; + uint64_t offset; + uint32_t data; + + if (bus > 255 || slot > 31 || func > 7 || reg > 4095) + return (~0U); + + sc = device_get_softc(dev); + + offset = PCIE_ADDR_OFFSET(bus, slot, func, reg); + t = sc->bst; + h = sc->bsh; + + switch (bytes) { + case 1: + data = bus_space_read_1(t, h, offset); + break; + case 2: + data = le16toh(bus_space_read_2(t, h, offset)); + break; + case 4: + data = le32toh(bus_space_read_4(t, h, offset)); + break; + default: + return (~0U); + } + + if (reg == PCIR_INTLINE) { + data += PCI_IRQ_START; + } + + return (data); +} + +static void +generic_pcie_write_config(device_t dev, u_int bus, u_int slot, + u_int func, u_int reg, uint32_t val, int bytes) +{ + struct generic_pcie_softc *sc; + bus_space_handle_t h; + bus_space_tag_t t; + uint64_t offset; + + if (bus > 255 || slot > 31 || func > 7 || reg > 4095) + return; + + sc = device_get_softc(dev); + + offset = PCIE_ADDR_OFFSET(bus, slot, func, reg); + + t = sc->bst; + h = sc->bsh; + + switch (bytes) { + case 1: + bus_space_write_1(t, h, offset, val); + break; + case 2: + bus_space_write_2(t, h, offset, htole16(val)); + break; + case 4: + bus_space_write_4(t, h, offset, htole32(val)); + break; + default: + return; + } +} + +static int +generic_pcie_maxslots(device_t dev) +{ + + return (31); /* max slots per bus acc. to standard */ +} + +static int +generic_pcie_read_ivar(device_t dev, device_t child, int index, + uintptr_t *result) +{ + struct generic_pcie_softc *sc; + int secondary_bus; + + sc = device_get_softc(dev); + + if (index == PCIB_IVAR_BUS) { + /* this pcib adds only pci bus 0 as child */ + secondary_bus = 0; + *result = secondary_bus; + return (0); + + } + + if (index == PCIB_IVAR_DOMAIN) { + *result = sc->ecam; + return (0); + } + + device_printf(dev, "ERROR: Unknown index.\n"); + return (ENOENT); +} + +static int +generic_pcie_write_ivar(device_t dev, device_t child, int index, + uintptr_t value) +{ + + return (ENOENT); +} + +static struct rman * +generic_pcie_rman(struct generic_pcie_softc *sc, int type) +{ + + switch (type) { + case SYS_RES_IOPORT: + return (&sc->io_rman); + case SYS_RES_MEMORY: + return (&sc->mem_rman); + case SYS_RES_IRQ: + return (&sc->irq_rman); + default: + break; + } + + return (NULL); +} + +static int +generic_pcie_release_resource(device_t dev, device_t child, int type, + int rid, struct resource *res) +{ + struct generic_pcie_softc *sc; + struct rman *rm; + + sc = device_get_softc(dev); + + rm = generic_pcie_rman(sc, type); + if (rm != NULL) { + KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); + rman_release_resource(res); + } + + return (bus_generic_release_resource(dev, child, type, rid, res)); +} + +static struct resource * +generic_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct generic_pcie_softc *sc; + struct resource *res; + struct rman *rm; + + sc = device_get_softc(dev); + + rm = generic_pcie_rman(sc, type); + if (rm == NULL) + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + type, rid, start, end, count, flags)); + + if (bootverbose) { + device_printf(dev, + "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n", + start, end, count); + } + + res = rman_reserve_resource(rm, start, end, count, flags, child); + if (res == NULL) + goto fail; + + rman_set_rid(res, *rid); + + if (flags & RF_ACTIVE) + if (bus_activate_resource(child, type, *rid, res)) { + rman_release_resource(res); + goto fail; + } + + return (res); + +fail: + if (bootverbose) { + device_printf(dev, "%s FAIL: type=%d, rid=%d, " + "start=%016lx, end=%016lx, count=%016lx, flags=%x\n", + __func__, type, *rid, start, end, count, flags); + } + + return (NULL); +} + +static int +generic_pcie_adjust_resource(device_t dev, device_t child, int type, + struct resource *res, u_long start, u_long end) +{ + struct generic_pcie_softc *sc; + struct rman *rm; + + sc = device_get_softc(dev); + + rm = generic_pcie_rman(sc, type); + if (rm != NULL) + return (rman_adjust_resource(res, start, end)); + return (bus_generic_adjust_resource(dev, child, type, res, start, end)); +} + +static int +generic_pcie_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct generic_pcie_softc *sc; + uint64_t phys_base; + uint64_t pci_base; + uint64_t size; + int found; + int res; + int i; + + sc = device_get_softc(dev); + + if ((res = rman_activate_resource(r)) != 0) + return (res); + + switch(type) { + case SYS_RES_IOPORT: + found = 0; + for (i = 0; i < MAX_RANGES_TUPLES; i++) { + pci_base = sc->ranges[i].pci_base; + phys_base = sc->ranges[i].phys_base; + size = sc->ranges[i].size; + + if ((rid > pci_base) && (rid < (pci_base + size))) { + found = 1; + break; + } + } + if (found) { + rman_set_start(r, rman_get_start(r) + phys_base); + BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, + type, rid, r); + } else { + device_printf(dev, "Failed to activate IOPORT resource\n"); + res = 0; + } + break; + case SYS_RES_MEMORY: + BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r); + break; + default: + break; + } + + return (res); +} + +static int +generic_pcie_deactivate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct generic_pcie_softc *sc; + vm_offset_t vaddr; + int res; + + sc = device_get_softc(dev); + + if ((res = rman_deactivate_resource(r)) != 0) + return (res); + + switch(type) { + case SYS_RES_IOPORT: + case SYS_RES_MEMORY: + vaddr = (vm_offset_t)rman_get_virtual(r); + pmap_unmapdev(vaddr, rman_get_size(r)); + break; + default: + break; + } + + return (res); +} + +static device_method_t generic_pcie_methods[] = { + DEVMETHOD(device_probe, generic_pcie_probe), + DEVMETHOD(device_attach, generic_pcie_attach), + DEVMETHOD(bus_read_ivar, generic_pcie_read_ivar), + DEVMETHOD(bus_write_ivar, generic_pcie_write_ivar), + DEVMETHOD(bus_alloc_resource, generic_pcie_alloc_resource), + DEVMETHOD(bus_adjust_resource, generic_pcie_adjust_resource), + DEVMETHOD(bus_release_resource, generic_pcie_release_resource), + DEVMETHOD(bus_activate_resource, generic_pcie_activate_resource), + DEVMETHOD(bus_deactivate_resource, generic_pcie_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(pcib_maxslots, generic_pcie_maxslots), + DEVMETHOD(pcib_read_config, generic_pcie_read_config), + DEVMETHOD(pcib_write_config, generic_pcie_write_config), + DEVMETHOD_END +}; + +static driver_t generic_pcie_driver = { + "pcib", + generic_pcie_methods, + sizeof(struct generic_pcie_softc), +}; + +static devclass_t generic_pcie_devclass; + +DRIVER_MODULE(pcib, simplebus, generic_pcie_driver, +generic_pcie_devclass, 0, 0); +DRIVER_MODULE(pcib, ofwbus, generic_pcie_driver, +generic_pcie_devclass, 0, 0); diff --git a/sys/dev/proto/proto_bus_pci.c b/sys/dev/proto/proto_bus_pci.c index 46ec41e..53ebb5e 100644 --- a/sys/dev/proto/proto_bus_pci.c +++ b/sys/dev/proto/proto_bus_pci.c @@ -82,6 +82,7 @@ proto_pci_attach(device_t dev) { struct proto_softc *sc; struct resource *res; + uint32_t val; int bar, rid, type; sc = device_get_softc(dev); @@ -91,15 +92,17 @@ proto_pci_attach(device_t dev) for (bar = 0; bar < PCIR_MAX_BAR_0; bar++) { rid = PCIR_BAR(bar); - type = SYS_RES_MEMORY; + val = pci_read_config(dev, rid, 4); + type = (PCI_BAR_IO(val)) ? SYS_RES_IOPORT : SYS_RES_MEMORY; res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); - if (res == NULL) { - type = SYS_RES_IOPORT; - res = bus_alloc_resource_any(dev, type, &rid, - RF_ACTIVE); - } - if (res != NULL) - proto_add_resource(sc, type, rid, res); + if (res == NULL) + continue; + proto_add_resource(sc, type, rid, res); + if (type == SYS_RES_IOPORT) + continue; + /* Skip over adjacent BAR for 64-bit memory BARs. */ + if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) + bar++; } rid = 0; diff --git a/sys/dev/proto/proto_busdma.c b/sys/dev/proto/proto_busdma.c index ced4eed..e01e76f 100644 --- a/sys/dev/proto/proto_busdma.c +++ b/sys/dev/proto/proto_busdma.c @@ -129,6 +129,16 @@ proto_busdma_tag_lookup(struct proto_busdma *busdma, u_long key) return (NULL); } +static void +proto_busdma_mem_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg, + int error) +{ + struct proto_ioc_busdma *ioc = arg; + + ioc->u.mem.bus_nsegs = nseg; + ioc->u.mem.bus_addr = segs[0].ds_addr; +} + static int proto_busdma_mem_alloc(struct proto_busdma *busdma, struct proto_tag *tag, struct proto_ioc_busdma *ioc) @@ -153,10 +163,18 @@ proto_busdma_mem_alloc(struct proto_busdma *busdma, struct proto_tag *tag, return (error); } md->physaddr = pmap_kextract((uintptr_t)(md->virtaddr)); + error = bus_dmamap_load(md->bd_tag, md->bd_map, md->virtaddr, + tag->maxsz, proto_busdma_mem_alloc_callback, ioc, BUS_DMA_NOWAIT); + if (error) { + bus_dmamem_free(md->bd_tag, md->virtaddr, md->bd_map); + bus_dma_tag_destroy(md->bd_tag); + free(md, M_PROTO_BUSDMA); + return (error); + } LIST_INSERT_HEAD(&tag->mds, md, peers); LIST_INSERT_HEAD(&busdma->mds, md, mds); - ioc->u.mem.nsegs = 1; - ioc->u.mem.physaddr = md->physaddr; + ioc->u.mem.phys_nsegs = 1; + ioc->u.mem.phys_addr = md->physaddr; ioc->result = (uintptr_t)(void *)md; return (0); } diff --git a/sys/dev/proto/proto_dev.h b/sys/dev/proto/proto_dev.h index 0050f0b..88a61a7 100644 --- a/sys/dev/proto/proto_dev.h +++ b/sys/dev/proto/proto_dev.h @@ -62,8 +62,10 @@ struct proto_ioc_busdma { struct { unsigned long tag; unsigned int flags; - unsigned int nsegs; - unsigned long physaddr; + unsigned int phys_nsegs; + unsigned long phys_addr; + unsigned long bus_addr; + unsigned int bus_nsegs; } mem; } u; unsigned long result; diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index b297502..7ba4dc9 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -69,6 +69,7 @@ struct pci_id { const char *desc; int rid; int rclk; + int regshft; }; static const struct pci_id pci_ns8250_ids[] = { @@ -118,6 +119,10 @@ static const struct pci_id pci_ns8250_ids[] = { { 0x151f, 0x0000, 0xffff, 0, "TOPIC Semiconductor TP560 56k modem", 0x10 }, { 0x1fd4, 0x1999, 0x1fd4, 0x0001, "Sunix SER5xxxx Serial Port", 0x10, 8 * DEFAULT_RCLK }, +{ 0x8086, 0x0f0a, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#1", 0x10, + 24 * DEFAULT_RCLK, 2 }, +{ 0x8086, 0x0f0c, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#2", 0x10, + 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 }, { 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x2a07, 0xffff, 0, "Intel AMT - PM965/GM965 KT Controller", 0x10 }, @@ -186,7 +191,7 @@ uart_pci_probe(device_t dev) return (ENXIO); match: - result = uart_bus_probe(dev, 0, id->rclk, id->rid, 0); + result = uart_bus_probe(dev, id->regshft, id->rclk, id->rid, 0); /* Bail out on error. */ if (result > 0) return (result); diff --git a/sys/dev/usb/misc/ugold.c b/sys/dev/usb/misc/ugold.c new file mode 100644 index 0000000..d6f8f77 --- /dev/null +++ b/sys/dev/usb/misc/ugold.c @@ -0,0 +1,405 @@ +/* $OpenBSD: ugold.c,v 1.7 2014/12/11 18:39:27 mpi Exp $ */ + +/* + * Copyright (c) 2013 Takayoshi SASANO <sasano@openbsd.org> + * Copyright (c) 2013 Martin Pieuchot <mpi@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Driver for Microdia's HID based TEMPer Temperature sensor */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stdint.h> +#include <sys/stddef.h> +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/module.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/condvar.h> +#include <sys/sysctl.h> +#include <sys/sx.h> +#include <sys/unistd.h> +#include <sys/callout.h> +#include <sys/malloc.h> +#include <sys/priv.h> +#include <sys/conf.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbhid.h> +#include <dev/usb/usb_process.h> +#include <dev/usb/usbdi_util.h> +#include "usbdevs.h" + +#define USB_DEBUG_VAR usb_debug +#include <dev/usb/usb_debug.h> + +#define UGOLD_INNER 0 +#define UGOLD_OUTER 1 +#define UGOLD_MAX_SENSORS 2 + +#define UGOLD_CMD_DATA 0x80 +#define UGOLD_CMD_INIT 0x82 + +enum { + UGOLD_INTR_DT, + UGOLD_N_TRANSFER, +}; + +/* + * This driver only uses two of the three known commands for the + * TEMPerV1.2 device. + * + * The first byte of the answer corresponds to the command and the + * second one seems to be the size (in bytes) of the answer. + * + * The device always sends 8 bytes and if the length of the answer + * is less than that, it just leaves the last bytes untouched. That + * is why most of the time the last n bytes of the answers are the + * same. + * + * The third command below seems to generate two answers with a + * string corresponding to the device, for example: + * 'TEMPer1F' and '1.1Per1F' (here Per1F is repeated). + */ +static uint8_t cmd_data[8] = {0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00}; +static uint8_t cmd_init[8] = {0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00}; + +#if 0 +static uint8_t cmd_type[8] = {0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00}; + +#endif + +struct ugold_softc; +struct ugold_readout_msg { + struct usb_proc_msg hdr; + struct ugold_softc *sc; +}; + +struct ugold_softc { + struct usb_device *sc_udev; + struct usb_xfer *sc_xfer[UGOLD_N_TRANSFER]; + + struct callout sc_callout; + struct mtx sc_mtx; + struct ugold_readout_msg sc_readout_msg[2]; + + int sc_num_sensors; + int sc_sensor[UGOLD_MAX_SENSORS]; + int sc_calib[UGOLD_MAX_SENSORS]; + int sc_valid[UGOLD_MAX_SENSORS]; + uint8_t sc_report_id; + uint8_t sc_iface_index[2]; +}; + +/* prototypes */ + +static device_probe_t ugold_probe; +static device_attach_t ugold_attach; +static device_detach_t ugold_detach; + +static usb_proc_callback_t ugold_readout_msg; + +static usb_callback_t ugold_intr_callback; + +static devclass_t ugold_devclass; + +static device_method_t ugold_methods[] = { + DEVMETHOD(device_probe, ugold_probe), + DEVMETHOD(device_attach, ugold_attach), + DEVMETHOD(device_detach, ugold_detach), + + DEVMETHOD_END +}; + +static driver_t ugold_driver = { + .name = "ugold", + .methods = ugold_methods, + .size = sizeof(struct ugold_softc), +}; + +DRIVER_MODULE(ugold, uhub, ugold_driver, ugold_devclass, NULL, NULL); +MODULE_DEPEND(ugold, usb, 1, 1, 1); +MODULE_VERSION(ugold, 1); + +static const struct usb_config ugold_config[UGOLD_N_TRANSFER] = { + + [UGOLD_INTR_DT] = { + .type = UE_INTERRUPT, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .bufsize = 0, /* use wMaxPacketSize */ + .callback = &ugold_intr_callback, + .if_index = 1, + }, +}; + +static const STRUCT_USB_HOST_ID ugold_devs[] = { + {USB_VPI(USB_VENDOR_CHICONY2, USB_PRODUCT_CHICONY2_TEMPER, 0)}, +}; + +static void +ugold_timeout(void *arg) +{ + struct ugold_softc *sc = arg; + + usb_proc_explore_lock(sc->sc_udev); + (void)usb_proc_explore_msignal(sc->sc_udev, + &sc->sc_readout_msg[0], &sc->sc_readout_msg[1]); + usb_proc_explore_unlock(sc->sc_udev); + + callout_reset(&sc->sc_callout, 6 * hz, &ugold_timeout, sc); +} + +static int +ugold_probe(device_t dev) +{ + struct usb_attach_arg *uaa; + + uaa = device_get_ivars(dev); + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bInterfaceClass != UICLASS_HID) + return (ENXIO); + if (uaa->info.bIfaceIndex != 0) + return (ENXIO); + + return (usbd_lookup_id_by_uaa(ugold_devs, sizeof(ugold_devs), uaa)); +} + +static int +ugold_attach(device_t dev) +{ + struct ugold_softc *sc = device_get_softc(dev); + struct usb_attach_arg *uaa = device_get_ivars(dev); + struct sysctl_oid *sensor_tree; + uint16_t d_len; + void *d_ptr; + int error; + int i; + + sc->sc_udev = uaa->device; + sc->sc_readout_msg[0].hdr.pm_callback = &ugold_readout_msg; + sc->sc_readout_msg[0].sc = sc; + sc->sc_readout_msg[1].hdr.pm_callback = &ugold_readout_msg; + sc->sc_readout_msg[1].sc = sc; + sc->sc_iface_index[0] = uaa->info.bIfaceIndex; + sc->sc_iface_index[1] = uaa->info.bIfaceIndex + 1; + + device_set_usb_desc(dev); + mtx_init(&sc->sc_mtx, "ugold lock", NULL, MTX_DEF | MTX_RECURSE); + callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0); + + /* grab all interfaces from other drivers */ + for (i = 0;; i++) { + if (i == uaa->info.bIfaceIndex) + continue; + if (usbd_get_iface(uaa->device, i) == NULL) + break; + + usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); + } + + /* figure out report ID */ + error = usbd_req_get_hid_desc(uaa->device, NULL, + &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); + + if (error) + goto detach; + + (void)hid_report_size(d_ptr, d_len, hid_input, &sc->sc_report_id); + + free(d_ptr, M_TEMP); + + error = usbd_transfer_setup(uaa->device, + sc->sc_iface_index, sc->sc_xfer, ugold_config, + UGOLD_N_TRANSFER, sc, &sc->sc_mtx); + if (error) + goto detach; + + sensor_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensors", + CTLFLAG_RD, NULL, ""); + + if (sensor_tree == NULL) { + error = ENOMEM; + goto detach; + } + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "inner", CTLFLAG_RD, &sc->sc_sensor[UGOLD_INNER], 0, + "Inner temperature in microCelcius"); + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "inner_valid", CTLFLAG_RD, &sc->sc_valid[UGOLD_INNER], 0, + "Inner temperature is valid"); + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "inner_calib", CTLFLAG_RWTUN, &sc->sc_calib[UGOLD_INNER], 0, + "Inner calibration temperature in microCelcius"); + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "outer", CTLFLAG_RD, &sc->sc_sensor[UGOLD_OUTER], 0, + "Outer temperature in microCelcius"); + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "outer_calib", CTLFLAG_RWTUN, &sc->sc_calib[UGOLD_OUTER], 0, + "Outer calibration temperature in microCelcius"); + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(sensor_tree), + OID_AUTO, "outer_valid", CTLFLAG_RD, &sc->sc_valid[UGOLD_OUTER], 0, + "Outer temperature is valid"); + + mtx_lock(&sc->sc_mtx); + usbd_transfer_start(sc->sc_xfer[UGOLD_INTR_DT]); + ugold_timeout(sc); + mtx_unlock(&sc->sc_mtx); + + return (0); + +detach: + DPRINTF("error=%s\n", usbd_errstr(error)); + ugold_detach(dev); + return (error); +} + +static int +ugold_detach(device_t dev) +{ + struct ugold_softc *sc = device_get_softc(dev); + + callout_drain(&sc->sc_callout); + + usb_proc_explore_lock(sc->sc_udev); + usb_proc_explore_mwait(sc->sc_udev, + &sc->sc_readout_msg[0], &sc->sc_readout_msg[1]); + usb_proc_explore_unlock(sc->sc_udev); + + usbd_transfer_unsetup(sc->sc_xfer, UGOLD_N_TRANSFER); + + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +static int +ugold_ds75_temp(uint8_t msb, uint8_t lsb) +{ + /* DS75: 12bit precision mode : 0.0625 degrees Celsius ticks */ + /* NOTE: MSB has a sign bit for negative temperatures */ + int32_t temp = (msb << 24) | ((lsb & 0xF0) << 16); + return (((int64_t)temp * (int64_t)1000000LL) >> 24); +} + + +static void +ugold_intr_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct ugold_softc *sc = usbd_xfer_softc(xfer); + struct usb_page_cache *pc; + uint8_t buf[8]; + int temp; + int len; + + usbd_xfer_status(xfer, &len, NULL, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + memset(buf, 0, sizeof(buf)); + + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_out(pc, 0, buf, MIN(len, sizeof(buf))); + + switch (buf[0]) { + case UGOLD_CMD_INIT: + if (sc->sc_num_sensors) + break; + + sc->sc_num_sensors = MIN(buf[1], UGOLD_MAX_SENSORS) /* XXX */ ; + + DPRINTF("%d sensor%s type ds75/12bit (temperature)\n", + sc->sc_num_sensors, (sc->sc_num_sensors == 1) ? "" : "s"); + break; + case UGOLD_CMD_DATA: + switch (buf[1]) { + case 4: + temp = ugold_ds75_temp(buf[4], buf[5]); + sc->sc_sensor[UGOLD_OUTER] = temp + sc->sc_calib[UGOLD_OUTER]; + sc->sc_valid[UGOLD_OUTER] = 1; + /* FALLTHROUGH */ + case 2: + temp = ugold_ds75_temp(buf[2], buf[3]); + sc->sc_sensor[UGOLD_INNER] = temp + sc->sc_calib[UGOLD_INNER]; + sc->sc_valid[UGOLD_INNER] = 1; + break; + default: + DPRINTF("invalid data length (%d bytes)\n", buf[1]); + } + break; + default: + DPRINTF("unknown command 0x%02x\n", buf[0]); + break; + } + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); + usbd_transfer_submit(xfer); + break; + default: /* Error */ + if (error != USB_ERR_CANCELLED) { + /* try clear stall first */ + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + break; + } +} + +static int +ugold_issue_cmd(struct ugold_softc *sc, uint8_t *cmd, int len) +{ + return (usbd_req_set_report(sc->sc_udev, &sc->sc_mtx, cmd, len, + sc->sc_iface_index[1], UHID_OUTPUT_REPORT, sc->sc_report_id)); +} + +static void +ugold_readout_msg(struct usb_proc_msg *pm) +{ + struct ugold_softc *sc = ((struct ugold_readout_msg *)pm)->sc; + + usb_proc_explore_unlock(sc->sc_udev); + + mtx_lock(&sc->sc_mtx); + if (sc->sc_num_sensors == 0) + ugold_issue_cmd(sc, cmd_init, sizeof(cmd_init)); + + ugold_issue_cmd(sc, cmd_data, sizeof(cmd_data)); + mtx_unlock(&sc->sc_mtx); + + usb_proc_explore_lock(sc->sc_udev); +} diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index b19f766..aaf1d67 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -525,7 +525,7 @@ vendor DMI 0x0c0b DMI vendor CANYON 0x0c10 Canyon vendor ICOM 0x0c26 Icom Inc. vendor GNOTOMETRICS 0x0c33 GN Otometrics -vendor CHICONY2 0x0c45 Chicony +vendor CHICONY2 0x0c45 Chicony / Microdia / Sonix Technology Co., Ltd. vendor REINERSCT 0x0c4b Reiner-SCT vendor SEALEVEL 0x0c52 Sealevel System vendor JETI 0x0c6c Jeti @@ -3050,6 +3050,11 @@ product MGE UPS2 0xffff MGE UPS SYSTEMS PROTECTIONCENTER 2 product MEI CASHFLOW_SC 0x1100 Cashflow-SC Cash Acceptor product MEI S2000 0x1101 Series 2000 Combo Acceptor +/* Microdia / Sonix Techonology Co., Ltd. products */ +product CHICONY2 YUREX 0x1010 YUREX +product CHICONY2 CAM_1 0x62c0 CAM_1 +product CHICONY2 TEMPER 0x7401 TEMPer sensor + /* Micro Star International products */ product MSI BT_DONGLE 0x1967 Bluetooth USB dongle product MSI RT3070_1 0x3820 RT3070 diff --git a/sys/dev/videomode/videomode.h b/sys/dev/videomode/videomode.h index b223da8..3e64444 100644 --- a/sys/dev/videomode/videomode.h +++ b/sys/dev/videomode/videomode.h @@ -43,6 +43,7 @@ struct videomode { int vtotal; int flags; /* Video mode flags; see below. */ const char *name; + int hskew; }; /* diff --git a/sys/dev/virtio/mmio/virtio_mmio.h b/sys/dev/virtio/mmio/virtio_mmio.h index 30e0286..81e87b7 100644 --- a/sys/dev/virtio/mmio/virtio_mmio.h +++ b/sys/dev/virtio/mmio/virtio_mmio.h @@ -36,10 +36,6 @@ #define VIRTIO_MMIO_MAGIC_VALUE 0x000 #define VIRTIO_MMIO_VERSION 0x004 #define VIRTIO_MMIO_DEVICE_ID 0x008 - -#define VIRTIO_MMIO_MAGIC_VALUE 0x000 -#define VIRTIO_MMIO_VERSION 0x004 -#define VIRTIO_MMIO_DEVICE_ID 0x008 #define VIRTIO_MMIO_VENDOR_ID 0x00c #define VIRTIO_MMIO_HOST_FEATURES 0x010 #define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index 704a3d9..3b6438f 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -443,7 +443,7 @@ vtnet_detach(device_t dev) sc->vtnet_vlan_attach = NULL; } if (sc->vtnet_vlan_detach != NULL) { - EVENTHANDLER_DEREGISTER(vlan_unconfg, sc->vtnet_vlan_detach); + EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vtnet_vlan_detach); sc->vtnet_vlan_detach = NULL; } @@ -1080,8 +1080,12 @@ vtnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) (IFF_PROMISC | IFF_ALLMULTI)) { if (sc->vtnet_flags & VTNET_FLAG_CTRL_RX) vtnet_rx_filter(sc); - else - error = ENOTSUP; + else { + ifp->if_flags |= IFF_PROMISC; + if ((ifp->if_flags ^ sc->vtnet_if_flags) + & IFF_ALLMULTI) + error = ENOTSUP; + } } } else vtnet_init_locked(sc); diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index d352242..459271e 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -85,11 +85,19 @@ __FBSDID("$FreeBSD$"); /*--------------------------- Compile-time Tunables --------------------------*/ /** + * The maximum number of shared memory ring pages we will allow in a + * negotiated block-front/back communication channel. Allow enough + * ring space for all requests to be XBB_MAX_REQUEST_SIZE'd. + */ +#define XBB_MAX_RING_PAGES 32 + +/** * The maximum number of outstanding request blocks (request headers plus * additional segment blocks) we will allow in a negotiated block-front/back * communication channel. */ -#define XBB_MAX_REQUESTS 256 +#define XBB_MAX_REQUESTS \ + __CONST_RING_SIZE(blkif, PAGE_SIZE * XBB_MAX_RING_PAGES) /** * \brief Define to force all I/O to be performed on memory owned by the @@ -148,14 +156,6 @@ static MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data"); (XBB_MAX_REQUEST_SIZE / PAGE_SIZE) + 1))) /** - * The maximum number of shared memory ring pages we will allow in a - * negotiated block-front/back communication channel. Allow enough - * ring space for all requests to be XBB_MAX_REQUEST_SIZE'd. - */ -#define XBB_MAX_RING_PAGES \ - BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBB_MAX_SEGMENTS_PER_REQUEST) \ - * XBB_MAX_REQUESTS) -/** * The maximum number of ring pages that we can allow per request list. * We limit this to the maximum number of segments per request, because * that is already a reasonable number of segments to aggregate. This @@ -1328,7 +1328,7 @@ xbb_queue_response(struct xbb_softc *xbb, struct xbb_xen_req *req, int status) if (status != BLKIF_RSP_OKAY) xbb->reqs_completed_with_error++; - xbb->rings.common.rsp_prod_pvt += BLKIF_SEGS_TO_BLOCKS(req->nr_pages); + xbb->rings.common.rsp_prod_pvt++; xbb->reqs_queued_for_completion++; @@ -1666,87 +1666,49 @@ xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) goto send_response; } - block_segs = MIN(nreq->nr_pages, - BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK); + block_segs = nseg; sg = ring_req->seg; last_block_sg = sg + block_segs; - while (1) { - - while (sg < last_block_sg) { - KASSERT(seg_idx < - XBB_MAX_SEGMENTS_PER_REQLIST, - ("seg_idx %d is too large, max " - "segs %d\n", seg_idx, - XBB_MAX_SEGMENTS_PER_REQLIST)); - - xbb_sg->first_sect = sg->first_sect; - xbb_sg->last_sect = sg->last_sect; - xbb_sg->nsect = - (int8_t)(sg->last_sect - - sg->first_sect + 1); - - if ((sg->last_sect >= (PAGE_SIZE >> 9)) - || (xbb_sg->nsect <= 0)) { - reqlist->status = BLKIF_RSP_ERROR; - goto send_response; - } - - nr_sects += xbb_sg->nsect; - map->host_addr = xbb_get_gntaddr(reqlist, - seg_idx, /*sector*/0); - KASSERT(map->host_addr + PAGE_SIZE <= - xbb->ring_config.gnt_addr, - ("Host address %#jx len %d overlaps " - "ring address %#jx\n", - (uintmax_t)map->host_addr, PAGE_SIZE, - (uintmax_t)xbb->ring_config.gnt_addr)); - - map->flags = GNTMAP_host_map; - map->ref = sg->gref; - map->dom = xbb->otherend_id; - if (operation == BIO_WRITE) - map->flags |= GNTMAP_readonly; - sg++; - map++; - xbb_sg++; - seg_idx++; - req_seg_idx++; - } - block_segs = MIN(nseg - req_seg_idx, - BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK); - if (block_segs == 0) - break; - - /* - * Fetch the next request block full of SG elements. - * For now, only the spacing between entries is - * different in the different ABIs, not the sg entry - * layout. - */ - req_ring_idx++; - switch (xbb->abi) { - case BLKIF_PROTOCOL_NATIVE: - sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.native, - req_ring_idx); - break; - case BLKIF_PROTOCOL_X86_32: - { - sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.x86_32, - req_ring_idx); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.x86_64, - req_ring_idx); - break; + while (sg < last_block_sg) { + KASSERT(seg_idx < + XBB_MAX_SEGMENTS_PER_REQLIST, + ("seg_idx %d is too large, max " + "segs %d\n", seg_idx, + XBB_MAX_SEGMENTS_PER_REQLIST)); + + xbb_sg->first_sect = sg->first_sect; + xbb_sg->last_sect = sg->last_sect; + xbb_sg->nsect = + (int8_t)(sg->last_sect - + sg->first_sect + 1); + + if ((sg->last_sect >= (PAGE_SIZE >> 9)) + || (xbb_sg->nsect <= 0)) { + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } - default: - panic("Unexpected blkif protocol ABI."); - /* NOTREACHED */ - } - last_block_sg = sg + block_segs; + + nr_sects += xbb_sg->nsect; + map->host_addr = xbb_get_gntaddr(reqlist, + seg_idx, /*sector*/0); + KASSERT(map->host_addr + PAGE_SIZE <= + xbb->ring_config.gnt_addr, + ("Host address %#jx len %d overlaps " + "ring address %#jx\n", + (uintmax_t)map->host_addr, PAGE_SIZE, + (uintmax_t)xbb->ring_config.gnt_addr)); + + map->flags = GNTMAP_host_map; + map->ref = sg->gref; + map->dom = xbb->otherend_id; + if (operation == BIO_WRITE) + map->flags |= GNTMAP_readonly; + sg++; + map++; + xbb_sg++; + seg_idx++; + req_seg_idx++; } /* Convert to the disk's sector size */ @@ -2000,8 +1962,7 @@ xbb_run_queue(void *context, int pending) * response be generated before we make room in * the queue for that response. */ - xbb->rings.common.req_cons += - BLKIF_SEGS_TO_BLOCKS(ring_req->nr_segments); + xbb->rings.common.req_cons++; xbb->reqs_received++; cur_size = xbb_count_sects(ring_req); @@ -3091,7 +3052,7 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) * Protocol defaults valid even if all negotiation fails. */ xbb->ring_config.ring_pages = 1; - xbb->max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; + xbb->max_request_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST; xbb->max_request_size = xbb->max_request_segments * PAGE_SIZE; /* @@ -3122,60 +3083,23 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) * fields. */ ring_page_order = 0; + xbb->max_requests = 32; + (void)xs_scanf(XST_NIL, otherend_path, "ring-page-order", NULL, "%u", &ring_page_order); xbb->ring_config.ring_pages = 1 << ring_page_order; - (void)xs_scanf(XST_NIL, otherend_path, - "num-ring-pages", NULL, "%u", - &xbb->ring_config.ring_pages); ring_size = PAGE_SIZE * xbb->ring_config.ring_pages; xbb->max_requests = BLKIF_MAX_RING_REQUESTS(ring_size); - (void)xs_scanf(XST_NIL, otherend_path, - "max-requests", NULL, "%u", - &xbb->max_requests); - - (void)xs_scanf(XST_NIL, otherend_path, - "max-request-segments", NULL, "%u", - &xbb->max_request_segments); - - (void)xs_scanf(XST_NIL, otherend_path, - "max-request-size", NULL, "%u", - &xbb->max_request_size); - if (xbb->ring_config.ring_pages > XBB_MAX_RING_PAGES) { xenbus_dev_fatal(xbb->dev, EINVAL, "Front-end specified ring-pages of %u " - "exceeds backend limit of %zu. " + "exceeds backend limit of %u. " "Unable to connect.", xbb->ring_config.ring_pages, XBB_MAX_RING_PAGES); return (EINVAL); - } else if (xbb->max_requests > XBB_MAX_REQUESTS) { - xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specified max_requests of %u " - "exceeds backend limit of %u. " - "Unable to connect.", - xbb->max_requests, - XBB_MAX_REQUESTS); - return (EINVAL); - } else if (xbb->max_request_segments > XBB_MAX_SEGMENTS_PER_REQUEST) { - xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specified max_requests_segments " - "of %u exceeds backend limit of %u. " - "Unable to connect.", - xbb->max_request_segments, - XBB_MAX_SEGMENTS_PER_REQUEST); - return (EINVAL); - } else if (xbb->max_request_size > XBB_MAX_REQUEST_SIZE) { - xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specified max_request_size " - "of %u exceeds backend limit of %u. " - "Unable to connect.", - xbb->max_request_size, - XBB_MAX_REQUEST_SIZE); - return (EINVAL); } if (xbb->ring_config.ring_pages == 1) { @@ -3723,18 +3647,6 @@ xbb_attach(device_t dev) return (error); } - /* - * Amazon EC2 client compatility. They refer to max-ring-pages - * instead of to max-ring-page-order. - */ - error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), - "max-ring-pages", "%zu", XBB_MAX_RING_PAGES); - if (error) { - xbb_attach_failed(xbb, error, "writing %s/max-ring-pages", - xenbus_get_node(xbb->dev)); - return (error); - } - max_ring_page_order = flsl(XBB_MAX_RING_PAGES) - 1; error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), "max-ring-page-order", "%u", max_ring_page_order); @@ -3744,32 +3656,6 @@ xbb_attach(device_t dev) return (error); } - error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), - "max-requests", "%u", XBB_MAX_REQUESTS); - if (error) { - xbb_attach_failed(xbb, error, "writing %s/max-requests", - xenbus_get_node(xbb->dev)); - return (error); - } - - error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), - "max-request-segments", "%u", - XBB_MAX_SEGMENTS_PER_REQUEST); - if (error) { - xbb_attach_failed(xbb, error, "writing %s/max-request-segments", - xenbus_get_node(xbb->dev)); - return (error); - } - - error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), - "max-request-size", "%u", - XBB_MAX_REQUEST_SIZE); - if (error) { - xbb_attach_failed(xbb, error, "writing %s/max-request-size", - xenbus_get_node(xbb->dev)); - return (error); - } - /* Collect physical device information. */ error = xs_gather(XST_NIL, xenbus_get_otherend_path(xbb->dev), "device-type", NULL, &xbb->dev_type, diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c index 92b5f35..3991f96 100644 --- a/sys/dev/xen/blkfront/blkfront.c +++ b/sys/dev/xen/blkfront/blkfront.c @@ -156,31 +156,71 @@ xbd_free_command(struct xbd_command *cm) } static void +mksegarray(bus_dma_segment_t *segs, int nsegs, + grant_ref_t * gref_head, int otherend_id, int readonly, + grant_ref_t * sg_ref, blkif_request_segment_t * sg) +{ + struct blkif_request_segment *last_block_sg = sg + nsegs; + vm_paddr_t buffer_ma; + uint64_t fsect, lsect; + int ref; + + while (sg < last_block_sg) { + buffer_ma = segs->ds_addr; + fsect = (buffer_ma & PAGE_MASK) >> XBD_SECTOR_SHFT; + lsect = fsect + (segs->ds_len >> XBD_SECTOR_SHFT) - 1; + + KASSERT(lsect <= 7, ("XEN disk driver data cannot " + "cross a page boundary")); + + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(gref_head); + + /* + * GNTTAB_LIST_END == 0xffffffff, but it is private + * to gnttab.c. + */ + KASSERT(ref != ~0, ("grant_reference failed")); + + gnttab_grant_foreign_access_ref( + ref, + otherend_id, + buffer_ma >> PAGE_SHIFT, + readonly); + + *sg_ref = ref; + *sg = (struct blkif_request_segment) { + .gref = ref, + .first_sect = fsect, + .last_sect = lsect + }; + sg++; + sg_ref++; + segs++; + } +} + +static void xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { struct xbd_softc *sc; struct xbd_command *cm; blkif_request_t *ring_req; - struct blkif_request_segment *sg; - struct blkif_request_segment *last_block_sg; - grant_ref_t *sg_ref; - vm_paddr_t buffer_ma; - uint64_t fsect, lsect; - int ref; int op; - int block_segs; cm = arg; sc = cm->cm_sc; if (error) { - printf("error %d in xbd_queue_cb\n", error); cm->cm_bp->bio_error = EIO; biodone(cm->cm_bp); xbd_free_command(cm); return; } + KASSERT(nsegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST, + ("Too many segments in a blkfront I/O")); + /* Fill out a communications ring structure. */ ring_req = RING_GET_REQUEST(&sc->xbd_ring, sc->xbd_ring.req_prod_pvt); sc->xbd_ring.req_prod_pvt++; @@ -190,57 +230,10 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) ring_req->handle = (blkif_vdev_t)(uintptr_t)sc->xbd_disk; ring_req->nr_segments = nsegs; cm->cm_nseg = nsegs; - - block_segs = MIN(nsegs, BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK); - sg = ring_req->seg; - last_block_sg = sg + block_segs; - sg_ref = cm->cm_sg_refs; - - while (1) { - - while (sg < last_block_sg) { - buffer_ma = segs->ds_addr; - fsect = (buffer_ma & PAGE_MASK) >> XBD_SECTOR_SHFT; - lsect = fsect + (segs->ds_len >> XBD_SECTOR_SHFT) - 1; - - KASSERT(lsect <= 7, ("XEN disk driver data cannot " - "cross a page boundary")); - - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&cm->cm_gref_head); - - /* - * GNTTAB_LIST_END == 0xffffffff, but it is private - * to gnttab.c. - */ - KASSERT(ref != ~0, ("grant_reference failed")); - - gnttab_grant_foreign_access_ref( - ref, - xenbus_get_otherend_id(sc->xbd_dev), - buffer_ma >> PAGE_SHIFT, - ring_req->operation == BLKIF_OP_WRITE); - - *sg_ref = ref; - *sg = (struct blkif_request_segment) { - .gref = ref, - .first_sect = fsect, - .last_sect = lsect - }; - sg++; - sg_ref++; - segs++; - nsegs--; - } - block_segs = MIN(nsegs, BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK); - if (block_segs == 0) - break; - - sg = BLKRING_GET_SEG_BLOCK(&sc->xbd_ring, - sc->xbd_ring.req_prod_pvt); - sc->xbd_ring.req_prod_pvt++; - last_block_sg = sg + block_segs; - } + mksegarray(segs, nsegs, &cm->cm_gref_head, + xenbus_get_otherend_id(sc->xbd_dev), + cm->cm_operation == BLKIF_OP_WRITE, + cm->cm_sg_refs, ring_req->seg); if (cm->cm_operation == BLKIF_OP_READ) op = BUS_DMASYNC_PREREAD; @@ -396,8 +389,8 @@ xbd_startio(struct xbd_softc *sc) if (sc->xbd_state != XBD_STATE_CONNECTED) return; - while (RING_FREE_REQUESTS(&sc->xbd_ring) >= - sc->xbd_max_request_blocks) { + while (!RING_FULL(&sc->xbd_ring)) { + if (sc->xbd_qfrozen_cnt != 0) break; @@ -450,13 +443,6 @@ xbd_bio_complete(struct xbd_softc *sc, struct xbd_command *cm) biodone(bp); } -static int -xbd_completion(struct xbd_command *cm) -{ - gnttab_end_foreign_access_references(cm->cm_nseg, cm->cm_sg_refs); - return (BLKIF_SEGS_TO_BLOCKS(cm->cm_nseg)); -} - static void xbd_int(void *xsc) { @@ -482,7 +468,9 @@ xbd_int(void *xsc) cm = &sc->xbd_shadow[bret->id]; xbd_remove_cm(cm, XBD_Q_BUSY); - i += xbd_completion(cm); + gnttab_end_foreign_access_references(cm->cm_nseg, + cm->cm_sg_refs); + i++; if (cm->cm_operation == BLKIF_OP_READ) op = BUS_DMASYNC_POSTREAD; @@ -1064,11 +1052,9 @@ xbd_initialize(struct xbd_softc *sc) */ max_ring_page_order = 0; sc->xbd_ring_pages = 1; - sc->xbd_max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; + sc->xbd_max_request_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST; sc->xbd_max_request_size = XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments); - sc->xbd_max_request_blocks = - BLKIF_SEGS_TO_BLOCKS(sc->xbd_max_request_segments); /* * Protocol negotiation. @@ -1095,24 +1081,10 @@ xbd_initialize(struct xbd_softc *sc) if (sc->xbd_ring_pages < 1) sc->xbd_ring_pages = 1; - sc->xbd_max_requests = - BLKIF_MAX_RING_REQUESTS(sc->xbd_ring_pages * PAGE_SIZE); - (void)xs_scanf(XST_NIL, otherend_path, - "max-requests", NULL, "%" PRIu32, - &sc->xbd_max_requests); - - (void)xs_scanf(XST_NIL, otherend_path, - "max-request-segments", NULL, "%" PRIu32, - &sc->xbd_max_request_segments); - - (void)xs_scanf(XST_NIL, otherend_path, - "max-request-size", NULL, "%" PRIu32, - &sc->xbd_max_request_size); - if (sc->xbd_ring_pages > XBD_MAX_RING_PAGES) { device_printf(sc->xbd_dev, "Back-end specified ring-pages of %u " - "limited to front-end limit of %zu.\n", + "limited to front-end limit of %u.\n", sc->xbd_ring_pages, XBD_MAX_RING_PAGES); sc->xbd_ring_pages = XBD_MAX_RING_PAGES; } @@ -1128,46 +1100,16 @@ xbd_initialize(struct xbd_softc *sc) sc->xbd_ring_pages = new_page_limit; } + sc->xbd_max_requests = + BLKIF_MAX_RING_REQUESTS(sc->xbd_ring_pages * PAGE_SIZE); if (sc->xbd_max_requests > XBD_MAX_REQUESTS) { device_printf(sc->xbd_dev, "Back-end specified max_requests of %u " - "limited to front-end limit of %u.\n", + "limited to front-end limit of %zu.\n", sc->xbd_max_requests, XBD_MAX_REQUESTS); sc->xbd_max_requests = XBD_MAX_REQUESTS; } - if (sc->xbd_max_request_segments > XBD_MAX_SEGMENTS_PER_REQUEST) { - device_printf(sc->xbd_dev, - "Back-end specified max_request_segments of %u " - "limited to front-end limit of %u.\n", - sc->xbd_max_request_segments, - XBD_MAX_SEGMENTS_PER_REQUEST); - sc->xbd_max_request_segments = XBD_MAX_SEGMENTS_PER_REQUEST; - } - - if (sc->xbd_max_request_size > XBD_MAX_REQUEST_SIZE) { - device_printf(sc->xbd_dev, - "Back-end specified max_request_size of %u " - "limited to front-end limit of %u.\n", - sc->xbd_max_request_size, - XBD_MAX_REQUEST_SIZE); - sc->xbd_max_request_size = XBD_MAX_REQUEST_SIZE; - } - - if (sc->xbd_max_request_size > - XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments)) { - device_printf(sc->xbd_dev, - "Back-end specified max_request_size of %u " - "limited to front-end limit of %u. (Too few segments.)\n", - sc->xbd_max_request_size, - XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments)); - sc->xbd_max_request_size = - XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments); - } - - sc->xbd_max_request_blocks = - BLKIF_SEGS_TO_BLOCKS(sc->xbd_max_request_segments); - /* Allocate datastructures based on negotiated values. */ error = bus_dma_tag_create( bus_get_dma_tag(sc->xbd_dev), /* parent */ @@ -1241,36 +1183,6 @@ xbd_initialize(struct xbd_softc *sc) } } - error = xs_printf(XST_NIL, node_path, - "max-requests","%u", - sc->xbd_max_requests); - if (error) { - xenbus_dev_fatal(sc->xbd_dev, error, - "writing %s/max-requests", - node_path); - return; - } - - error = xs_printf(XST_NIL, node_path, - "max-request-segments","%u", - sc->xbd_max_request_segments); - if (error) { - xenbus_dev_fatal(sc->xbd_dev, error, - "writing %s/max-request-segments", - node_path); - return; - } - - error = xs_printf(XST_NIL, node_path, - "max-request-size","%u", - sc->xbd_max_request_size); - if (error) { - xenbus_dev_fatal(sc->xbd_dev, error, - "writing %s/max-request-size", - node_path); - return; - } - error = xs_printf(XST_NIL, node_path, "event-channel", "%u", xen_intr_port(sc->xen_intr_handle)); if (error) { diff --git a/sys/dev/xen/blkfront/block.h b/sys/dev/xen/blkfront/block.h index 9c803bc..3007118 100644 --- a/sys/dev/xen/blkfront/block.h +++ b/sys/dev/xen/blkfront/block.h @@ -61,11 +61,19 @@ ((size / PAGE_SIZE) + 1) /** + * The maximum number of shared memory ring pages we will allow in a + * negotiated block-front/back communication channel. Allow enough + * ring space for all requests to be XBD_MAX_REQUEST_SIZE'd. + */ +#define XBD_MAX_RING_PAGES 32 + +/** * The maximum number of outstanding requests blocks (request headers plus * additional segment blocks) we will allow in a negotiated block-front/back * communication channel. */ -#define XBD_MAX_REQUESTS 256 +#define XBD_MAX_REQUESTS \ + __CONST_RING_SIZE(blkif, PAGE_SIZE * XBD_MAX_RING_PAGES) /** * The maximum mapped region size per request we will allow in a negotiated @@ -83,15 +91,6 @@ (MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ XBD_SIZE_TO_SEGS(XBD_MAX_REQUEST_SIZE))) -/** - * The maximum number of shared memory ring pages we will allow in a - * negotiated block-front/back communication channel. Allow enough - * ring space for all requests to be XBD_MAX_REQUEST_SIZE'd. - */ -#define XBD_MAX_RING_PAGES \ - BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBD_MAX_SEGMENTS_PER_REQUEST) \ - * XBD_MAX_REQUESTS) - typedef enum { XBDCF_Q_MASK = 0xFF, /* This command has contributed to xbd_qfrozen_cnt. */ @@ -175,7 +174,6 @@ struct xbd_softc { u_int xbd_ring_pages; uint32_t xbd_max_requests; uint32_t xbd_max_request_segments; - uint32_t xbd_max_request_blocks; uint32_t xbd_max_request_size; grant_ref_t xbd_ring_ref[XBD_MAX_RING_PAGES]; blkif_front_ring_t xbd_ring; diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c index d3d8ce0..f379c5a 100644 --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -199,9 +199,7 @@ fdesc_statfs(mp, sbp) * limit is ever reduced below the current number * of open files... ] */ - PROC_LOCK(td->td_proc); - lim = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(td->td_proc); + lim = lim_cur(td, RLIMIT_NOFILE); fdp = td->td_proc->p_fd; FILEDESC_SLOCK(fdp); limit = racct_get_limit(td->td_proc, RACCT_NOFILE); diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 9c98832..15f3bd4 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -482,7 +482,7 @@ fdesc_setattr(ap) /* * Allow setattr where there is an underlying vnode. */ - error = getvnode(td->td_proc->p_fd, fd, + error = getvnode(td, fd, cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) { /* diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index e8de4a5..53ba7ef 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -129,12 +129,6 @@ ncl_getpages(struct vop_getpages_args *ap) npages = btoc(count); /* - * Since the caller has busied the requested page, that page's valid - * field will not be changed by other threads. - */ - vm_page_assert_xbusied(pages[ap->a_reqpage]); - - /* * If the requested page is partially valid, just return it and * allow the pager to zero-out the blanks. Partially valid pages * can only occur at the file EOF. diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 2e35582..6114608 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1031,6 +1031,7 @@ tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de) tmpfs_free_dirent(tmp, xde); } } + de->td_cookie = de->td_hash; } else RB_REMOVE(tmpfs_dir, head, de); @@ -1320,7 +1321,7 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize, boolean_t ignerr) struct tmpfs_mount *tmp; struct tmpfs_node *node; vm_object_t uobj; - vm_page_t m, ma[1]; + vm_page_t m; vm_pindex_t idx, newpages, oldpages; off_t oldsize; int base, rv; @@ -1367,11 +1368,9 @@ retry: VM_WAIT; VM_OBJECT_WLOCK(uobj); goto retry; - } else if (m->valid != VM_PAGE_BITS_ALL) { - ma[0] = m; - rv = vm_pager_get_pages(uobj, ma, 1, 0); - m = vm_page_lookup(uobj, idx); - } else + } else if (m->valid != VM_PAGE_BITS_ALL) + rv = vm_pager_get_pages(uobj, &m, 1, 0); + else /* A cached page was reactivated. */ rv = VM_PAGER_OK; vm_page_lock(m); diff --git a/sys/geom/label/g_label.c b/sys/geom/label/g_label.c index 36498e1..b4a1365 100644 --- a/sys/geom/label/g_label.c +++ b/sys/geom/label/g_label.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/libkern.h> #include <sys/sbuf.h> +#include <sys/stddef.h> #include <sys/sysctl.h> #include <geom/geom.h> #include <geom/geom_slice.h> @@ -96,6 +97,20 @@ const struct g_label_desc *g_labels[] = { NULL }; +void +g_label_rtrim(char *label, size_t size) +{ + ptrdiff_t i; + + for (i = size - 1; i >= 0; i--) { + if (label[i] == '\0') + continue; + else if (label[i] == ' ') + label[i] = '\0'; + else + break; + } +} static int g_label_destroy_geom(struct gctl_req *req __unused, struct g_class *mp, diff --git a/sys/geom/label/g_label.h b/sys/geom/label/g_label.h index 66b762c..9092d98 100644 --- a/sys/geom/label/g_label.h +++ b/sys/geom/label/g_label.h @@ -86,6 +86,8 @@ extern struct g_label_desc g_label_ntfs; extern struct g_label_desc g_label_gpt; extern struct g_label_desc g_label_gpt_uuid; extern struct g_label_desc g_label_disk_ident; + +extern void g_label_rtrim(char *label, size_t size); #endif /* _KERNEL */ struct g_label_metadata { diff --git a/sys/geom/label/g_label_iso9660.c b/sys/geom/label/g_label_iso9660.c index 154cefc..c3c49b0 100644 --- a/sys/geom/label/g_label_iso9660.c +++ b/sys/geom/label/g_label_iso9660.c @@ -47,7 +47,6 @@ g_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; char *sector, *volume; - int i; g_topology_assert_not(); pp = cp->provider; @@ -68,14 +67,7 @@ g_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size) bzero(label, size); strlcpy(label, volume, MIN(size, VOLUME_LEN)); g_free(sector); - for (i = size - 1; i > 0; i--) { - if (label[i] == '\0') - continue; - else if (label[i] == ' ') - label[i] = '\0'; - else - break; - } + g_label_rtrim(label, size); } struct g_label_desc g_label_iso9660 = { diff --git a/sys/geom/label/g_label_msdosfs.c b/sys/geom/label/g_label_msdosfs.c index 5f65a72..918fabc 100644 --- a/sys/geom/label/g_label_msdosfs.c +++ b/sys/geom/label/g_label_msdosfs.c @@ -48,7 +48,6 @@ g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size) FAT32_BSBPB *pfat32_bsbpb; FAT_DES *pfat_entry; uint8_t *sector0, *sector; - uint32_t i; g_topology_assert_not(); pp = cp->provider; @@ -200,14 +199,7 @@ g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size) } endofchecks: - for (i = size - 1; i > 0; i--) { - if (label[i] == '\0') - continue; - else if (label[i] == ' ') - label[i] = '\0'; - else - break; - } + g_label_rtrim(label, size); error: if (sector0 != NULL) diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index e5710bf..1bf8163 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -17,6 +17,23 @@ profile 2 # options KDTRACE_HOOKS +# DTrace core +# NOTE: introduces CDDL-licensed components into the kernel +#device dtrace + +# DTrace modules +#device dtrace_lockstat +#device dtrace_profile +#device dtrace_sdt +#device dtrace_fbt +#device dtrace_systrace +#device dtrace_prototype +#device dtnfscl +#device dtmalloc + +# Alternatively include all the DTrace modules +#device dtraceall + ##################################################################### # SMP OPTIONS: diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index 39a8828..70c6d9d 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -157,9 +157,12 @@ IDTVEC(xmm) .type alltraps,@function alltraps: pushal - pushl %ds - pushl %es - pushl %fs + pushl $0 + movl %ds,(%esp) + pushl $0 + movl %es,(%esp) + pushl $0 + movl %fs,(%esp) alltraps_with_regs_pushed: SET_KERNEL_SREGS cld @@ -233,9 +236,12 @@ IDTVEC(lcall_syscall) pushl $7 /* sizeof "lcall 7,0" */ subl $4,%esp /* skip over tf_trapno */ pushal - pushl %ds - pushl %es - pushl %fs + pushl $0 + movl %ds,(%esp) + pushl $0 + movl %es,(%esp) + pushl $0 + movl %fs,(%esp) SET_KERNEL_SREGS cld FAKE_MCOUNT(TF_EIP(%esp)) @@ -259,9 +265,12 @@ IDTVEC(int0x80_syscall) pushl $2 /* sizeof "int 0x80" */ subl $4,%esp /* skip over tf_trapno */ pushal - pushl %ds - pushl %es - pushl %fs + pushl $0 + movl %ds,(%esp) + pushl $0 + movl %es,(%esp) + pushl $0 + movl %fs,(%esp) SET_KERNEL_SREGS cld FAKE_MCOUNT(TF_EIP(%esp)) @@ -416,13 +425,16 @@ doreti_iret: doreti_iret_fault: subl $8,%esp pushal - pushl %ds + pushl $0 + movl %ds,(%esp) .globl doreti_popl_ds_fault doreti_popl_ds_fault: - pushl %es + pushl $0 + movl %es,(%esp) .globl doreti_popl_es_fault doreti_popl_es_fault: - pushl %fs + pushl $0 + movl %fs,(%esp) .globl doreti_popl_fs_fault doreti_popl_fs_fault: sti diff --git a/sys/i386/i386/gdb_machdep.c b/sys/i386/i386/gdb_machdep.c index a42b2b6..06809ad 100644 --- a/sys/i386/i386/gdb_machdep.c +++ b/sys/i386/i386/gdb_machdep.c @@ -45,14 +45,22 @@ __FBSDID("$FreeBSD$"); void * gdb_cpu_getreg(int regnum, size_t *regsz) { + static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL); + static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL); + static uint32_t _kprivsel = GSEL(GPRIV_SEL, SEL_KPL); *regsz = gdb_cpu_regsz(regnum); - if (kdb_thread == curthread) { + if (kdb_thread == curthread) { switch (regnum) { case 0: return (&kdb_frame->tf_eax); case 1: return (&kdb_frame->tf_ecx); case 2: return (&kdb_frame->tf_edx); + case 9: return (&kdb_frame->tf_eflags); + case 10: return (&kdb_frame->tf_cs); + case 12: return (&kdb_frame->tf_ds); + case 13: return (&kdb_frame->tf_es); + case 14: return (&kdb_frame->tf_fs); } } switch (regnum) { @@ -62,6 +70,12 @@ gdb_cpu_getreg(int regnum, size_t *regsz) case 6: return (&kdb_thrctx->pcb_esi); case 7: return (&kdb_thrctx->pcb_edi); case 8: return (&kdb_thrctx->pcb_eip); + case 10: return (&_kcodesel); + case 11: return (&_kdatasel); + case 12: return (&_kdatasel); + case 13: return (&_kdatasel); + case 14: return (&_kprivsel); + case 15: return (&kdb_thrctx->pcb_gs); } return (NULL); } diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 2763ef7..0373b6f 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2867,6 +2867,7 @@ makectx(struct trapframe *tf, struct pcb *pcb) pcb->pcb_ebx = tf->tf_ebx; pcb->pcb_eip = tf->tf_eip; pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8; + pcb->pcb_gs = rgs(); } int diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 1ca406b..1e417bf 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -306,8 +306,8 @@ trap(struct trapframe *frame) td->td_pticks = 0; td->td_frame = frame; addr = frame->tf_eip; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 2c2cae4..ccf5190 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -98,40 +98,30 @@ ibcs2_ulimit(td, uap) struct ibcs2_ulimit_args *uap; { struct rlimit rl; - struct proc *p; int error; #define IBCS2_GETFSIZE 1 #define IBCS2_SETFSIZE 2 #define IBCS2_GETPSIZE 3 #define IBCS2_GETDTABLESIZE 4 - p = td->td_proc; switch (uap->cmd) { case IBCS2_GETFSIZE: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE); if (td->td_retval[0] == -1) td->td_retval[0] = 0x7fffffff; return 0; case IBCS2_SETFSIZE: - PROC_LOCK(p); - rl.rlim_max = lim_max(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + rl.rlim_max = lim_max(td, RLIMIT_FSIZE); rl.rlim_cur = uap->newlimit; error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); if (!error) { - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE); } else { DPRINTF(("failed ")); } return error; case IBCS2_GETPSIZE: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_RSS); /* XXX */ return 0; case IBCS2_GETDTABLESIZE: uap->cmd = IBCS2_SC_OPEN_MAX; @@ -352,8 +342,7 @@ ibcs2_getdents(td, uap) #define BSD_DIRENT(cp) ((struct dirent *)(cp)) #define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -508,8 +497,7 @@ ibcs2_read(td, uap) u_long *cookies = NULL, *cookiep; int ncookies; - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) { if (error == EINVAL) return sys_read(td, (struct read_args *)uap); @@ -801,18 +789,14 @@ ibcs2_sysconf(td, uap) struct ibcs2_sysconf_args *uap; { int mib[2], value, len, error; - struct proc *p; - p = td->td_proc; switch(uap->name) { case IBCS2_SC_ARG_MAX: mib[1] = KERN_ARGMAX; break; case IBCS2_SC_CHILD_MAX: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_NPROC); return 0; case IBCS2_SC_CLK_TCK: @@ -824,9 +808,7 @@ ibcs2_sysconf(td, uap) break; case IBCS2_SC_OPEN_MAX: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_NOFILE); return 0; case IBCS2_SC_JOB_CONTROL: diff --git a/sys/i386/include/asmacros.h b/sys/i386/include/asmacros.h index 716915c..91c25f7 100644 --- a/sys/i386/include/asmacros.h +++ b/sys/i386/include/asmacros.h @@ -146,9 +146,12 @@ pushl $0 ; /* dummy error code */ \ pushl $0 ; /* dummy trap type */ \ pushal ; /* 8 ints */ \ - pushl %ds ; /* save data and extra segments ... */ \ - pushl %es ; \ - pushl %fs + pushl $0 ; /* save data and extra segments ... */ \ + mov %ds,(%esp) ; \ + pushl $0 ; \ + mov %es,(%esp) ; \ + pushl $0 ; \ + mov %fs,(%esp) #define POP_FRAME \ popl %fs ; \ diff --git a/sys/i386/include/gdb_machdep.h b/sys/i386/include/gdb_machdep.h index 95af8d4..a60ba18 100644 --- a/sys/i386/include/gdb_machdep.h +++ b/sys/i386/include/gdb_machdep.h @@ -30,7 +30,7 @@ #define _MACHINE_GDB_MACHDEP_H_ #define GDB_BUFSZ 400 -#define GDB_NREGS 14 +#define GDB_NREGS 16 #define GDB_REG_PC 8 static __inline size_t diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 0a4114b..9363b47 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -108,7 +108,7 @@ exec_linux_imgact(struct image_params *imgp) */ PROC_LOCK(imgp->proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index c9f969b..4fb5785 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -509,7 +509,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - - lim_cur(p, RLIMIT_STACK); + lim_cur_proc(p, RLIMIT_STACK); PROC_UNLOCK(p); } diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index edd5f5f..3165ac0 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -248,7 +248,7 @@ exec_aout_imgact(struct image_params *imgp) a_out->a_text > maxtsiz || /* data + bss can't exceed rlimit */ - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/kern/imgact_binmisc.c b/sys/kern/imgact_binmisc.c index 5f324d3..5ee9bb8 100644 --- a/sys/kern/imgact_binmisc.c +++ b/sys/kern/imgact_binmisc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2013, Stacey D. Son + * Copyright (c) 2013-15, Stacey D. Son * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/sysctl.h> +#include <sys/sx.h> + +#include <machine/atomic.h> /** * Miscellaneous binary interpreter image activator. @@ -96,7 +99,7 @@ static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list = static int interp_list_entry_count = 0; -static struct mtx interp_list_mtx; +static struct sx interp_list_sx; int imgact_binmisc_exec(struct image_params *imgp); @@ -111,7 +114,7 @@ imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe) char t[IBE_INTERP_LEN_MAX]; char *sp, *tp; - bzero(t, sizeof(t)); + memset(t, 0, sizeof(t)); /* * Normalize interpreter string. Replace white space between args with @@ -152,8 +155,6 @@ imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe) imgact_binmisc_entry_t *ibe = NULL; size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX); - mtx_assert(&interp_list_mtx, MA_NOTOWNED); - ibe = malloc(sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO); ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO); @@ -203,7 +204,7 @@ imgact_binmisc_find_entry(char *name) { imgact_binmisc_entry_t *ibe; - mtx_assert(&interp_list_mtx, MA_OWNED); + sx_assert(&interp_list_sx, SA_LOCKED); SLIST_FOREACH(ibe, &interpreter_list, link) { if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0) @@ -260,21 +261,20 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe) } } - mtx_lock(&interp_list_mtx); + sx_xlock(&interp_list_sx); if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { - mtx_unlock(&interp_list_mtx); + sx_xunlock(&interp_list_sx); return (EEXIST); } - mtx_unlock(&interp_list_mtx); + /* Preallocate a new entry. */ ibe = imgact_binmisc_new_entry(xbe); if (!ibe) return (ENOMEM); - mtx_lock(&interp_list_mtx); SLIST_INSERT_HEAD(&interpreter_list, ibe, link); interp_list_entry_count++; - mtx_unlock(&interp_list_mtx); + sx_xunlock(&interp_list_sx); return (0); } @@ -288,14 +288,14 @@ imgact_binmisc_remove_entry(char *name) { imgact_binmisc_entry_t *ibe; - mtx_lock(&interp_list_mtx); + sx_xlock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - mtx_unlock(&interp_list_mtx); + sx_xunlock(&interp_list_sx); return (ENOENT); } SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); interp_list_entry_count--; - mtx_unlock(&interp_list_mtx); + sx_xunlock(&interp_list_sx); imgact_binmisc_destroy_entry(ibe); @@ -311,14 +311,14 @@ imgact_binmisc_disable_entry(char *name) { imgact_binmisc_entry_t *ibe; - mtx_lock(&interp_list_mtx); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (ENOENT); } - ibe->ibe_flags &= ~IBF_ENABLED; - mtx_unlock(&interp_list_mtx); + atomic_clear_32(&ibe->ibe_flags, IBF_ENABLED); + sx_sunlock(&interp_list_sx); return (0); } @@ -332,14 +332,14 @@ imgact_binmisc_enable_entry(char *name) { imgact_binmisc_entry_t *ibe; - mtx_lock(&interp_list_mtx); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (ENOENT); } - ibe->ibe_flags |= IBF_ENABLED; - mtx_unlock(&interp_list_mtx); + atomic_set_32(&ibe->ibe_flags, IBF_ENABLED); + sx_sunlock(&interp_list_sx); return (0); } @@ -350,9 +350,9 @@ imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, { uint32_t i; - mtx_assert(&interp_list_mtx, MA_OWNED); + sx_assert(&interp_list_sx, SA_LOCKED); - bzero(xbe, sizeof(*xbe)); + memset(xbe, 0, sizeof(*xbe)); strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX); /* Copy interpreter string. Replace NULL breaks with space. */ @@ -382,14 +382,14 @@ imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe) imgact_binmisc_entry_t *ibe; int error = 0; - mtx_lock(&interp_list_mtx); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (ENOENT); } error = imgact_binmisc_populate_xbe(xbe, ibe); - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (error); } @@ -404,14 +404,9 @@ imgact_binmisc_get_all_entries(struct sysctl_req *req) imgact_binmisc_entry_t *ibe; int error = 0, count; - mtx_lock(&interp_list_mtx); + sx_slock(&interp_list_sx); count = interp_list_entry_count; - /* Don't block in malloc() while holding lock. */ - xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_NOWAIT|M_ZERO); - if (!xbe) { - mtx_unlock(&interp_list_mtx); - return (ENOMEM); - } + xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_WAITOK|M_ZERO); xbep = xbe; SLIST_FOREACH(ibe, &interpreter_list, link) { @@ -419,7 +414,7 @@ imgact_binmisc_get_all_entries(struct sysctl_req *req) if (error) break; } - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); if (!error) error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count); @@ -556,7 +551,7 @@ imgact_binmisc_find_interpreter(const char *image_header) int i; size_t sz; - mtx_assert(&interp_list_mtx, MA_OWNED); + sx_assert(&interp_list_sx, SA_LOCKED); SLIST_FOREACH(ibe, &interpreter_list, link) { if (!(IBF_ENABLED & ibe->ibe_flags)) @@ -593,15 +588,15 @@ imgact_binmisc_exec(struct image_params *imgp) char *s, *d; /* Do we have an interpreter for the given image header? */ - mtx_lock(&interp_list_mtx); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (-1); } /* No interpreter nesting allowed. */ if (imgp->interpreted & IMGACT_BINMISC) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); return (ENOEXEC); } @@ -649,7 +644,7 @@ imgact_binmisc_exec(struct image_params *imgp) default: /* Hmm... This shouldn't happen. */ - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); printf("%s: Unknown macro #%c sequence in " "interpreter string\n", KMOD_NAME, *(s + 1)); error = EINVAL; @@ -660,7 +655,7 @@ imgact_binmisc_exec(struct image_params *imgp) /* Check to make sure we won't overrun the stringspace. */ if (offset > imgp->args->stringspace) { - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); error = E2BIG; goto done; } @@ -720,7 +715,7 @@ imgact_binmisc_exec(struct image_params *imgp) s++; } *d = '\0'; - mtx_unlock(&interp_list_mtx); + sx_sunlock(&interp_list_sx); if (!error) imgp->interpreter_name = imgp->args->begin_argv; @@ -736,7 +731,7 @@ static void imgact_binmisc_init(void *arg) { - mtx_init(&interp_list_mtx, KMOD_NAME, NULL, MTX_DEF); + sx_init(&interp_list_sx, KMOD_NAME); } static void @@ -745,15 +740,15 @@ imgact_binmisc_fini(void *arg) imgact_binmisc_entry_t *ibe, *ibe_tmp; /* Free all the interpreters. */ - mtx_lock(&interp_list_mtx); + sx_xlock(&interp_list_sx); SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) { SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); imgact_binmisc_destroy_entry(ibe); } - mtx_unlock(&interp_list_mtx); + sx_xunlock(&interp_list_sx); - mtx_destroy(&interp_list_mtx); + sx_destroy(&interp_list_sx); } SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, 0); diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index c3953fe..0675128 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -908,11 +908,11 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * not actually fault in all the segments pages. */ PROC_LOCK(imgp->proc); - if (data_size > lim_cur(imgp->proc, RLIMIT_DATA)) + if (data_size > lim_cur_proc(imgp->proc, RLIMIT_DATA)) err_str = "Data segment size exceeds process limit"; else if (text_size > maxtsiz) err_str = "Text segment size exceeds system limit"; - else if (total_size > lim_cur(imgp->proc, RLIMIT_VMEM)) + else if (total_size > lim_cur_proc(imgp->proc, RLIMIT_VMEM)) err_str = "Total segment size exceeds process limit"; else if (racct_set(imgp->proc, RACCT_DATA, data_size) != 0) err_str = "Data segment size exceeds resource limit"; @@ -936,7 +936,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * calculation is that it leaves room for the heap to grow to * its maximum allowed size. */ - addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(imgp->proc, + addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(curthread, RLIMIT_DATA)); PROC_UNLOCK(imgp->proc); @@ -1983,7 +1983,7 @@ note_procstat_rlimit(void *arg, struct sbuf *sb, size_t *sizep) sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); for (i = 0; i < RLIM_NLIMITS; i++) - lim_rlimit(p, i, &rlim[i]); + lim_rlimit_proc(p, i, &rlim[i]); PROC_UNLOCK(p); sbuf_bcat(sb, rlim, sizeof(rlim)); } diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c index ab77a88..47b7280 100644 --- a/sys/kern/imgact_gzip.c +++ b/sys/kern/imgact_gzip.c @@ -212,7 +212,7 @@ do_aout_hdr(struct imgact_gzip * gz) /* data + bss can't exceed rlimit */ gz->a_out.a_data + gz->bss_size > - lim_cur(gz->ip->proc, RLIMIT_DATA) || + lim_cur_proc(gz->ip->proc, RLIMIT_DATA) || racct_set(gz->ip->proc, RACCT_DATA, gz->a_out.a_data + gz->bss_size) != 0) { PROC_UNLOCK(gz->ip->proc); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index cf4eed1..37539c4 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -523,8 +523,6 @@ proc0_init(void *dummy __unused) #ifdef MAC mac_cred_create_swapper(newcred); #endif - td->td_ucred = crhold(newcred); - /* Create sigacts. */ p->p_sigacts = sigacts_alloc(); @@ -556,6 +554,10 @@ proc0_init(void *dummy __unused) p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = pageablemem; p->p_cpulimit = RLIM_INFINITY; + PROC_LOCK(p); + thread_cow_get_proc(td, p); + PROC_UNLOCK(p); + /* Initialize resource accounting structures. */ racct_create(&p->p_racct); @@ -843,10 +845,10 @@ create_init(const void *udata __unused) audit_cred_proc1(newcred); #endif proc_set_cred(initproc, newcred); + cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); PROC_UNLOCK(initproc); sx_xunlock(&proctree_lock); crfree(oldcred); - cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); } SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7848396..8220786 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -109,7 +109,7 @@ static void fdgrowtable(struct filedesc *fdp, int nfd); static void fdgrowtable_exp(struct filedesc *fdp, int nfd); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); -static int getmaxfd(struct proc *p); +static int getmaxfd(struct thread *td); /* Flags for do_dup() */ #define DUP_FIXED 0x1 /* Force fixed allocation. */ @@ -178,9 +178,6 @@ volatile int openfiles; /* actual number of open files */ struct mtx sigio_lock; /* mtx to protect pointers to sigio */ void (*mq_fdclose)(struct thread *td, int fd, struct file *fp); -/* A mutex to protect the association between a proc and filedesc. */ -static struct mtx fdesc_mtx; - /* * If low >= size, just return low. Otherwise find the first zero bit in the * given bitmap, starting at low and not exceeding size - 1. Return size if @@ -312,7 +309,7 @@ fdfree(struct filedesc *fdp, int fd) seq_write_begin(&fde->fde_seq); #endif fdefree_last(fde); - bzero(fde, fde_change_size); + fde->fde_file = NULL; fdunused(fdp, fd); #ifdef CAPABILITIES seq_write_end(&fde->fde_seq); @@ -331,16 +328,19 @@ struct getdtablesize_args { int sys_getdtablesize(struct thread *td, struct getdtablesize_args *uap) { - struct proc *p = td->td_proc; +#ifdef RACCT uint64_t lim; +#endif - PROC_LOCK(p); td->td_retval[0] = - min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); + min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc); +#ifdef RACCT + PROC_LOCK(td->td_proc); lim = racct_get_limit(td->td_proc, RACCT_NOFILE); - PROC_UNLOCK(p); + PROC_UNLOCK(td->td_proc); if (lim < td->td_retval[0]) td->td_retval[0] = lim; +#endif return (0); } @@ -746,7 +746,8 @@ 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, NULL, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights), &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -783,15 +784,10 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } static int -getmaxfd(struct proc *p) +getmaxfd(struct thread *td) { - int maxfd; - PROC_LOCK(p); - maxfd = min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); - PROC_UNLOCK(p); - - return (maxfd); + return (min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc)); } /* @@ -819,7 +815,7 @@ do_dup(struct thread *td, int flags, int old, int new) return (EBADF); if (new < 0) return (flags & DUP_FCNTL ? EINVAL : EBADF); - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); if (new >= maxfd) return (flags & DUP_FCNTL ? EINVAL : EBADF); @@ -1619,7 +1615,7 @@ fdalloc(struct thread *td, int minfd, int *result) if (fdp->fd_freefile > minfd) minfd = fdp->fd_freefile; - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); /* * Search the bitmap for a free descriptor starting at minfd. @@ -1656,7 +1652,6 @@ fdalloc(struct thread *td, int minfd, int *result) ("fd_first_free() returned non-free descriptor")); KASSERT(fdp->fd_ofiles[fd].fde_file == NULL, ("file descriptor isn't free")); - KASSERT(fdp->fd_ofiles[fd].fde_flags == 0, ("file flags are set")); fdused(fdp, fd); *result = fd; return (0); @@ -1755,32 +1750,23 @@ falloc_noinstall(struct thread *td, struct file **resultfp) /* * Install a file in a file descriptor table. */ -int -finstall(struct thread *td, struct file *fp, int *fd, int flags, +void +_finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, struct filecaps *fcaps) { - struct filedesc *fdp = td->td_proc->p_fd; struct filedescent *fde; - int error; - KASSERT(fd != NULL, ("%s: fd == NULL", __func__)); - KASSERT(fp != NULL, ("%s: fp == NULL", __func__)); + MPASS(fp != NULL); if (fcaps != NULL) filecaps_validate(fcaps, __func__); + FILEDESC_XLOCK_ASSERT(fdp); - FILEDESC_XLOCK(fdp); - if ((error = fdalloc(td, 0, fd))) { - FILEDESC_XUNLOCK(fdp); - return (error); - } - fhold(fp); - fde = &fdp->fd_ofiles[*fd]; + fde = &fdp->fd_ofiles[fd]; #ifdef CAPABILITIES seq_write_begin(&fde->fde_seq); #endif fde->fde_file = fp; - if ((flags & O_CLOEXEC) != 0) - fde->fde_flags |= UF_EXCLOSE; + fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0; if (fcaps != NULL) filecaps_move(fcaps, &fde->fde_caps); else @@ -1788,6 +1774,24 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags, #ifdef CAPABILITIES seq_write_end(&fde->fde_seq); #endif +} + +int +finstall(struct thread *td, struct file *fp, int *fd, int flags, + struct filecaps *fcaps) +{ + struct filedesc *fdp = td->td_proc->p_fd; + int error; + + MPASS(fd != NULL); + + FILEDESC_XLOCK(fdp); + if ((error = fdalloc(td, 0, fd))) { + FILEDESC_XUNLOCK(fdp); + return (error); + } + fhold(fp); + _finstall(fdp, fp, *fd, flags, fcaps); FILEDESC_XUNLOCK(fdp); return (0); } @@ -1809,8 +1813,8 @@ fdinit(struct filedesc *fdp, bool prepfiles) /* Create the file descriptor table. */ FILEDESC_LOCK_INIT(newfdp); - newfdp->fd_refcnt = 1; - newfdp->fd_holdcnt = 1; + refcount_init(&newfdp->fd_refcnt, 1); + refcount_init(&newfdp->fd_holdcnt, 1); newfdp->fd_cmask = CMASK; newfdp->fd_map = newfdp0->fd_dmap; newfdp->fd_lastfile = -1; @@ -1852,24 +1856,19 @@ fdhold(struct proc *p) { struct filedesc *fdp; - mtx_lock(&fdesc_mtx); + PROC_LOCK_ASSERT(p, MA_OWNED); fdp = p->p_fd; if (fdp != NULL) - fdp->fd_holdcnt++; - mtx_unlock(&fdesc_mtx); + refcount_acquire(&fdp->fd_holdcnt); return (fdp); } static void fddrop(struct filedesc *fdp) { - int i; if (fdp->fd_holdcnt > 1) { - mtx_lock(&fdesc_mtx); - i = --fdp->fd_holdcnt; - mtx_unlock(&fdesc_mtx); - if (i > 0) + if (refcount_release(&fdp->fd_holdcnt) == 0) return; } @@ -1884,9 +1883,7 @@ struct filedesc * fdshare(struct filedesc *fdp) { - FILEDESC_XLOCK(fdp); - fdp->fd_refcnt++; - FILEDESC_XUNLOCK(fdp); + refcount_acquire(&fdp->fd_refcnt); return (fdp); } @@ -2032,6 +2029,7 @@ retry: void fdescfree(struct thread *td) { + struct proc *p; struct filedesc0 *fdp0; struct filedesc *fdp; struct freetable *ft, *tft; @@ -2040,31 +2038,29 @@ fdescfree(struct thread *td) struct vnode *cdir, *jdir, *rdir; int i; - fdp = td->td_proc->p_fd; + p = td->td_proc; + fdp = p->p_fd; MPASS(fdp != NULL); #ifdef RACCT if (racct_enable) { - PROC_LOCK(td->td_proc); - racct_set(td->td_proc, RACCT_NOFILE, 0); - PROC_UNLOCK(td->td_proc); + PROC_LOCK(p); + racct_set(p, RACCT_NOFILE, 0); + PROC_UNLOCK(p); } #endif if (td->td_proc->p_fdtol != NULL) fdclearlocks(td); - mtx_lock(&fdesc_mtx); - td->td_proc->p_fd = NULL; - mtx_unlock(&fdesc_mtx); + PROC_LOCK(p); + p->p_fd = NULL; + PROC_UNLOCK(p); - FILEDESC_XLOCK(fdp); - i = --fdp->fd_refcnt; - if (i > 0) { - FILEDESC_XUNLOCK(fdp); + if (refcount_release(&fdp->fd_refcnt) == 0) return; - } + FILEDESC_XLOCK(fdp); cdir = fdp->fd_cdir; fdp->fd_cdir = NULL; rdir = fdp->fd_rdir; @@ -2373,11 +2369,9 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, if (fp == NULL) return (EBADF); #ifdef CAPABILITIES - if (needrightsp != NULL) { - error = cap_check(&haverights, needrightsp); - if (error != 0) - return (error); - } + error = cap_check(&haverights, needrightsp); + if (error != 0) + return (error); #endif retry: count = fp->f_count; @@ -2438,11 +2432,9 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, *fpp = NULL; fdp = td->td_proc->p_fd; - if (needrightsp != NULL) - needrights = *needrightsp; - else - cap_rights_init(&needrights); - error = fget_unlocked(fdp, fd, &needrights, &fp, seqp); + if (needrightsp == NULL) + needrightsp = cap_rights_init(&needrights); + error = fget_unlocked(fdp, fd, needrightsp, &fp, seqp); if (error != 0) return (error); if (fp->f_ops == &badfileops) { @@ -2855,7 +2847,7 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, seq_write_begin(&newfde->fde_seq); #endif memcpy(newfde, oldfde, fde_change_size); - bzero(oldfde, fde_change_size); + oldfde->fde_file = NULL; fdunused(fdp, dfd); #ifdef CAPABILITIES seq_write_end(&newfde->fde_seq); @@ -2884,7 +2876,9 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) nrele = 0; sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { + PROC_LOCK(p); fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; FILEDESC_XLOCK(fdp); @@ -2979,9 +2973,13 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) n = 0; sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { - if (p->p_state == PRS_NEW) + PROC_LOCK(p); + if (p->p_state == PRS_NEW) { + PROC_UNLOCK(p); continue; + } fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; /* overestimates sparse tables. */ @@ -3008,8 +3006,8 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) } xf.xf_pid = p->p_pid; xf.xf_uid = p->p_ucred->cr_uid; - PROC_UNLOCK(p); fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; FILEDESC_SLOCK(fdp); @@ -3644,7 +3642,6 @@ filelistinit(void *dummy) filedesc0_zone = uma_zcreate("filedesc0", sizeof(struct filedesc0), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mtx_init(&sigio_lock, "sigio lock", NULL, MTX_DEF); - mtx_init(&fdesc_mtx, "fdesc", NULL, MTX_DEF); } SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL); diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 9000add..ff17fe9 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -754,14 +754,10 @@ kern_kqueue(struct thread *td, int flags) p = td->td_proc; cred = td->td_ucred; crhold(cred); - PROC_LOCK(p); - if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td->td_proc, - RLIMIT_KQUEUES))) { - PROC_UNLOCK(p); + if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_KQUEUES))) { crfree(cred); return (ENOMEM); } - PROC_UNLOCK(p); fdp = p->p_fd; error = falloc(td, &fp, &fd, flags); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 8668f0d..375e644 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -966,13 +966,10 @@ exec_map_first_page(imgp) } initial_pagein = i; rv = vm_pager_get_pages(object, ma, initial_pagein, 0); - ma[0] = vm_page_lookup(object, 0); - if ((rv != VM_PAGER_OK) || (ma[0] == NULL)) { - if (ma[0] != NULL) { - vm_page_lock(ma[0]); - vm_page_free(ma[0]); - vm_page_unlock(ma[0]); - } + if (rv != VM_PAGER_OK) { + vm_page_lock(ma[0]); + vm_page_free(ma[0]); + vm_page_unlock(ma[0]); VM_OBJECT_WUNLOCK(object); return (EIO); } @@ -1073,7 +1070,7 @@ exec_new_vmspace(imgp, sv) if (imgp->stack_sz != 0) { ssiz = trunc_page(imgp->stack_sz); PROC_LOCK(p); - lim_rlimit(p, RLIMIT_STACK, &rlim_stack); + lim_rlimit_proc(p, RLIMIT_STACK, &rlim_stack); PROC_UNLOCK(p); if (ssiz > rlim_stack.rlim_max) ssiz = rlim_stack.rlim_max; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index a3fde18..3fd4f09 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -496,7 +496,6 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, p2->p_swtick = ticks; if (p1->p_flag & P_PROFIL) startprofclock(p2); - td2->td_ucred = crhold(p2->p_ucred); if (flags & RFSIGSHARE) { p2->p_sigacts = sigacts_hold(p1->p_sigacts); @@ -526,6 +525,8 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, */ lim_fork(p1, p2); + thread_cow_get_proc(td2, p2); + pstats_fork(p1->p_stats, p2->p_stats); PROC_UNLOCK(p1); @@ -911,10 +912,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, if (error == 0) ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, 0); else { - PROC_LOCK(p1); ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, - lim_cur(p1, RLIMIT_NPROC)); - PROC_UNLOCK(p1); + lim_cur(td, RLIMIT_NPROC)); } if (ok) { do_fork(td, flags, newproc, td2, vm2, pdflags); diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index c87c4e2..c118d74 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -1331,7 +1331,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) pr->pr_securelevel = ppr->pr_securelevel; pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow; - pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; + pr->pr_enforce_statfs = jail_default_enforce_statfs; pr->pr_devfs_rsnum = ppr->pr_devfs_rsnum; pr->pr_osreldate = osreldt ? osreldt : ppr->pr_osreldate; diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index ee94de0..863bbc6 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -289,7 +289,7 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p, cpu_set_fork_handler(newtd, func, arg); newtd->td_pflags |= TDP_KTHREAD; - newtd->td_ucred = crhold(p->p_ucred); + thread_cow_get_proc(newtd, p); /* this code almost the same as create_thread() in kern_thr.c */ p->p_flag |= P_HADTHREADS; diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index ea6f7a6..72fc434 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -384,6 +384,7 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts, uint64_t spin_cnt = 0; uint64_t sleep_cnt = 0; int64_t sleep_time = 0; + int64_t all_time = 0; #endif if (SCHEDULER_STOPPED()) @@ -414,6 +415,9 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts, CTR4(KTR_LOCK, "_mtx_lock_sleep: %s contested (lock=%p) at %s:%d", m->lock_object.lo_name, (void *)m->mtx_lock, file, line); +#ifdef KDTRACE_HOOKS + all_time -= lockstat_nsecs(); +#endif while (!_mtx_obtain_lock(m, tid)) { #ifdef KDTRACE_HOOKS @@ -517,6 +521,9 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts, sleep_cnt++; #endif } +#ifdef KDTRACE_HOOKS + all_time += lockstat_nsecs(); +#endif #ifdef KTR if (cont_logged) { CTR4(KTR_CONTENTION, @@ -534,7 +541,7 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts, * Only record the loops spinning and not sleeping. */ if (spin_cnt > sleep_cnt) - LOCKSTAT_RECORD1(LS_MTX_LOCK_SPIN, m, (spin_cnt - sleep_cnt)); + LOCKSTAT_RECORD1(LS_MTX_LOCK_SPIN, m, (all_time - sleep_time)); #endif } @@ -574,6 +581,9 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts, int contested = 0; uint64_t waittime = 0; #endif +#ifdef KDTRACE_HOOKS + int64_t spin_time = 0; +#endif if (SCHEDULER_STOPPED()) return; @@ -589,6 +599,9 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts, PMC_SOFT_CALL( , , lock, failed); #endif lock_profile_obtain_lock_failed(&m->lock_object, &contested, &waittime); +#ifdef KDTRACE_HOOKS + spin_time -= lockstat_nsecs(); +#endif while (!_mtx_obtain_lock(m, tid)) { /* Give interrupts a chance while we spin. */ @@ -606,6 +619,9 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts, } spinlock_enter(); } +#ifdef KDTRACE_HOOKS + spin_time += lockstat_nsecs(); +#endif if (LOCK_LOG_TEST(&m->lock_object, opts)) CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m); @@ -614,7 +630,7 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts, LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_ACQUIRE, m, contested, waittime, (file), (line)); - LOCKSTAT_RECORD1(LS_MTX_SPIN_LOCK_SPIN, m, i); + LOCKSTAT_RECORD1(LS_MTX_SPIN_LOCK_SPIN, m, spin_time); } #endif /* SMP */ @@ -629,7 +645,7 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) uint64_t waittime = 0; #endif #ifdef KDTRACE_HOOKS - uint64_t spin_cnt = 0; + int64_t spin_time = 0; #endif i = 0; @@ -638,6 +654,9 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) if (SCHEDULER_STOPPED()) return; +#ifdef KDTRACE_HOOKS + spin_time -= lockstat_nsecs(); +#endif for (;;) { retry: spinlock_enter(); @@ -654,9 +673,6 @@ retry: WITNESS_CHECKORDER(&m->lock_object, opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line, NULL); while (!_mtx_obtain_lock(m, tid)) { -#ifdef KDTRACE_HOOKS - spin_cnt++; -#endif if (m->mtx_lock == tid) { m->mtx_recurse++; break; @@ -685,17 +701,17 @@ retry: if (m == td->td_lock) break; __mtx_unlock_spin(m); /* does spinlock_exit() */ + } #ifdef KDTRACE_HOOKS - spin_cnt++; + spin_time += lockstat_nsecs(); #endif - } if (m->mtx_recurse == 0) LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_ACQUIRE, m, contested, waittime, (file), (line)); LOCK_LOG_LOCK("LOCK", &m->lock_object, opts, m->mtx_recurse, file, line); WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line); - LOCKSTAT_RECORD1(LS_THREAD_LOCK_SPIN, m, spin_cnt); + LOCKSTAT_RECORD1(LS_THREAD_LOCK_SPIN, m, spin_time); } struct mtx * diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index fc33feb..27c6f40 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2615,7 +2615,7 @@ sysctl_kern_proc_rlimit(SYSCTL_HANDLER_ARGS) */ if (req->oldptr != NULL) { PROC_LOCK(p); - lim_rlimit(p, which, &rlim); + lim_rlimit_proc(p, which, &rlim); PROC_UNLOCK(p); } error = SYSCTL_OUT(req, &rlim, sizeof(rlim)); diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 9c49f71..b531763 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1946,9 +1946,8 @@ cred_update_thread(struct thread *td) p = td->td_proc; cred = td->td_ucred; - PROC_LOCK(p); + PROC_LOCK_ASSERT(p, MA_OWNED); td->td_ucred = crhold(p->p_ucred); - PROC_UNLOCK(p); if (cred != NULL) crfree(cred); } @@ -1987,6 +1986,8 @@ proc_set_cred(struct proc *p, struct ucred *newcred) oldcred = p->p_ucred; p->p_ucred = newcred; + if (newcred != NULL) + PROC_UPDATE_COW(p); return (oldcred); } diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index e8ae9fe..2a10790 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -500,7 +500,7 @@ racct_destroy(struct racct **racct) * may be less than zero. */ static void -racct_alloc_resource(struct racct *racct, int resource, +racct_adjust_resource(struct racct *racct, int resource, uint64_t amount) { @@ -553,7 +553,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount) return (error); } #endif - racct_alloc_resource(p->p_racct, resource, amount); + racct_adjust_resource(p->p_racct, resource, amount); racct_add_cred_locked(p->p_ucred, resource, amount); return (0); @@ -587,11 +587,11 @@ racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount) SDT_PROBE(racct, kernel, rusage, add__cred, cred, resource, amount, 0, 0); - racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount); + racct_adjust_resource(cred->cr_ruidinfo->ui_racct, resource, amount); for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) - racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, + racct_adjust_resource(pr->pr_prison_racct->prr_racct, resource, amount); - racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount); + racct_adjust_resource(cred->cr_loginclass->lc_racct, resource, amount); } /* @@ -631,7 +631,7 @@ racct_add_force(struct proc *p, int resource, uint64_t amount) PROC_LOCK_ASSERT(p, MA_OWNED); mtx_lock(&racct_lock); - racct_alloc_resource(p->p_racct, resource, amount); + racct_adjust_resource(p->p_racct, resource, amount); mtx_unlock(&racct_lock); racct_add_cred(p->p_ucred, resource, amount); } @@ -685,7 +685,7 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount) } } #endif - racct_alloc_resource(p->p_racct, resource, diff_proc); + racct_adjust_resource(p->p_racct, resource, diff_proc); if (diff_cred > 0) racct_add_cred_locked(p->p_ucred, resource, diff_cred); else if (diff_cred < 0) @@ -747,7 +747,7 @@ racct_set_force_locked(struct proc *p, int resource, uint64_t amount) } else diff_cred = diff_proc; - racct_alloc_resource(p->p_racct, resource, diff_proc); + racct_adjust_resource(p->p_racct, resource, diff_proc); if (diff_cred > 0) racct_add_cred_locked(p->p_ucred, resource, diff_cred); else if (diff_cred < 0) @@ -849,7 +849,7 @@ racct_sub(struct proc *p, int resource, uint64_t amount) "than allocated %jd for %s (pid %d)", __func__, amount, resource, (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid)); - racct_alloc_resource(p->p_racct, resource, -amount); + racct_adjust_resource(p->p_racct, resource, -amount); racct_sub_cred_locked(p->p_ucred, resource, amount); mtx_unlock(&racct_lock); } @@ -870,11 +870,11 @@ racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount) resource)); #endif - racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount); + racct_adjust_resource(cred->cr_ruidinfo->ui_racct, resource, -amount); for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) - racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, + racct_adjust_resource(pr->pr_prison_racct->prr_racct, resource, -amount); - racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount); + racct_adjust_resource(cred->cr_loginclass->lc_racct, resource, -amount); } /* diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index dac49cd..546f3b2 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -560,15 +560,11 @@ ogetrlimit(struct thread *td, register struct ogetrlimit_args *uap) { struct orlimit olim; struct rlimit rl; - struct proc *p; int error; if (uap->which >= RLIM_NLIMITS) return (EINVAL); - p = td->td_proc; - PROC_LOCK(p); - lim_rlimit(p, uap->which, &rl); - PROC_UNLOCK(p); + lim_rlimit(td, uap->which, &rl); /* * XXX would be more correct to convert only RLIM_INFINITY to the @@ -625,7 +621,7 @@ lim_cb(void *arg) } PROC_STATUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { - lim_rlimit(p, RLIMIT_CPU, &rlim); + lim_rlimit_proc(p, RLIMIT_CPU, &rlim); if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) { killproc(p, "exceeded maximum CPU limit"); } else { @@ -667,29 +663,21 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, limp->rlim_max = RLIM_INFINITY; oldssiz.rlim_cur = 0; - newlim = NULL; + newlim = lim_alloc(); PROC_LOCK(p); - if (lim_shared(p->p_limit)) { - PROC_UNLOCK(p); - newlim = lim_alloc(); - PROC_LOCK(p); - } oldlim = p->p_limit; alimp = &oldlim->pl_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) if ((error = priv_check(td, PRIV_PROC_SETRLIMIT))) { PROC_UNLOCK(p); - if (newlim != NULL) - lim_free(newlim); + lim_free(newlim); return (error); } if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; - if (newlim != NULL) { - lim_copy(newlim, oldlim); - alimp = &newlim->pl_rlimit[which]; - } + lim_copy(newlim, oldlim); + alimp = &newlim->pl_rlimit[which]; switch (which) { @@ -739,11 +727,10 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, if (p->p_sysent->sv_fixlimit != NULL) p->p_sysent->sv_fixlimit(limp, which); *alimp = *limp; - if (newlim != NULL) - p->p_limit = newlim; + p->p_limit = newlim; + PROC_UPDATE_COW(p); PROC_UNLOCK(p); - if (newlim != NULL) - lim_free(oldlim); + lim_free(oldlim); if (which == RLIMIT_STACK && /* @@ -793,15 +780,11 @@ int sys_getrlimit(struct thread *td, register struct __getrlimit_args *uap) { struct rlimit rlim; - struct proc *p; int error; if (uap->which >= RLIM_NLIMITS) return (EINVAL); - p = td->td_proc; - PROC_LOCK(p); - lim_rlimit(p, uap->which, &rlim); - PROC_UNLOCK(p); + lim_rlimit(td, uap->which, &rlim); error = copyout(&rlim, uap->rlp, sizeof(struct rlimit)); return (error); } @@ -1172,11 +1155,20 @@ lim_copy(struct plimit *dst, struct plimit *src) * which parameter specifies the index into the rlimit array. */ rlim_t -lim_max(struct proc *p, int which) +lim_max(struct thread *td, int which) { struct rlimit rl; - lim_rlimit(p, which, &rl); + lim_rlimit(td, which, &rl); + return (rl.rlim_max); +} + +rlim_t +lim_max_proc(struct proc *p, int which) +{ + struct rlimit rl; + + lim_rlimit_proc(p, which, &rl); return (rl.rlim_max); } @@ -1185,11 +1177,20 @@ lim_max(struct proc *p, int which) * The which parameter which specifies the index into the rlimit array */ rlim_t -lim_cur(struct proc *p, int which) +lim_cur(struct thread *td, int which) { struct rlimit rl; - lim_rlimit(p, which, &rl); + lim_rlimit(td, which, &rl); + return (rl.rlim_cur); +} + +rlim_t +lim_cur_proc(struct proc *p, int which) +{ + struct rlimit rl; + + lim_rlimit_proc(p, which, &rl); return (rl.rlim_cur); } @@ -1198,7 +1199,20 @@ lim_cur(struct proc *p, int which) * specified by 'which' in the rlimit structure pointed to by 'rlp'. */ void -lim_rlimit(struct proc *p, int which, struct rlimit *rlp) +lim_rlimit(struct thread *td, int which, struct rlimit *rlp) +{ + struct proc *p = td->td_proc; + + MPASS(td == curthread); + KASSERT(which >= 0 && which < RLIM_NLIMITS, + ("request for invalid resource limit")); + *rlp = td->td_limit->pl_rlimit[which]; + if (p->p_sysent->sv_fixlimit != NULL) + p->p_sysent->sv_fixlimit(rlp, which); +} + +void +lim_rlimit_proc(struct proc *p, int which, struct rlimit *rlp) { PROC_LOCK_ASSERT(p, MA_OWNED); @@ -1441,3 +1455,17 @@ chgkqcnt(struct uidinfo *uip, int diff, rlim_t max) } return (1); } + +void +lim_update_thread(struct thread *td) +{ + struct proc *p; + struct plimit *lim; + + p = td->td_proc; + lim = td->td_limit; + PROC_LOCK_ASSERT(p, MA_OWNED); + td->td_limit = lim_hold(p->p_limit); + if (lim != NULL) + lim_free(lim); +} diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index d3cfbdd..f75912b 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -300,6 +300,9 @@ __rw_try_wlock(volatile uintptr_t *c, const char *file, int line) if (rval) { WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file, line); + if (!rw_recursed(rw)) + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_RW_WLOCK_ACQUIRE, + rw, 0, 0, file, line); curthread->td_locks++; } return (rval); @@ -352,9 +355,11 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line) #endif uintptr_t v; #ifdef KDTRACE_HOOKS + uintptr_t state; uint64_t spin_cnt = 0; uint64_t sleep_cnt = 0; int64_t sleep_time = 0; + int64_t all_time = 0; #endif if (SCHEDULER_STOPPED()) @@ -372,6 +377,10 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line) rw->lock_object.lo_name, file, line)); WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line, NULL); +#ifdef KDTRACE_HOOKS + all_time -= lockstat_nsecs(); + state = rw->rw_lock; +#endif for (;;) { #ifdef KDTRACE_HOOKS spin_cnt++; @@ -534,7 +543,19 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line) CTR2(KTR_LOCK, "%s: %p resuming from turnstile", __func__, rw); } +#ifdef KDTRACE_HOOKS + all_time += lockstat_nsecs(); + if (sleep_time) + LOCKSTAT_RECORD4(LS_RW_RLOCK_BLOCK, rw, sleep_time, + LOCKSTAT_READER, (state & RW_LOCK_READ) == 0, + (state & RW_LOCK_READ) == 0 ? 0 : RW_READERS(state)); + /* Record only the loops spinning and not sleeping. */ + if (spin_cnt > sleep_cnt) + LOCKSTAT_RECORD4(LS_RW_RLOCK_SPIN, rw, all_time - sleep_time, + LOCKSTAT_READER, (state & RW_LOCK_READ) == 0, + (state & RW_LOCK_READ) == 0 ? 0 : RW_READERS(state)); +#endif /* * TODO: acquire "owner of record" here. Here be turnstile dragons * however. turnstiles don't like owners changing between calls to @@ -546,16 +567,6 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line) WITNESS_LOCK(&rw->lock_object, 0, file, line); curthread->td_locks++; curthread->td_rw_rlocks++; -#ifdef KDTRACE_HOOKS - if (sleep_time) - LOCKSTAT_RECORD1(LS_RW_RLOCK_BLOCK, rw, sleep_time); - - /* - * Record only the loops spinning and not sleeping. - */ - if (spin_cnt > sleep_cnt) - LOCKSTAT_RECORD1(LS_RW_RLOCK_SPIN, rw, (spin_cnt - sleep_cnt)); -#endif } int @@ -583,6 +594,8 @@ __rw_try_rlock(volatile uintptr_t *c, const char *file, int line) LOCK_LOG_TRY("RLOCK", &rw->lock_object, 0, 1, file, line); WITNESS_LOCK(&rw->lock_object, LOP_TRYLOCK, file, line); + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_RW_RLOCK_ACQUIRE, + rw, 0, 0, file, line); curthread->td_locks++; curthread->td_rw_rlocks++; return (1); @@ -727,9 +740,11 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file, int contested = 0; #endif #ifdef KDTRACE_HOOKS + uintptr_t state; uint64_t spin_cnt = 0; uint64_t sleep_cnt = 0; int64_t sleep_time = 0; + int64_t all_time = 0; #endif if (SCHEDULER_STOPPED()) @@ -751,6 +766,10 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file, CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__, rw->lock_object.lo_name, (void *)rw->rw_lock, file, line); +#ifdef KDTRACE_HOOKS + all_time -= lockstat_nsecs(); + state = rw->rw_lock; +#endif while (!_rw_write_lock(rw, tid)) { #ifdef KDTRACE_HOOKS spin_cnt++; @@ -888,18 +907,21 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file, spintries = 0; #endif } - LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_RW_WLOCK_ACQUIRE, rw, contested, - waittime, file, line); #ifdef KDTRACE_HOOKS + all_time += lockstat_nsecs(); if (sleep_time) - LOCKSTAT_RECORD1(LS_RW_WLOCK_BLOCK, rw, sleep_time); + LOCKSTAT_RECORD4(LS_RW_WLOCK_BLOCK, rw, sleep_time, + LOCKSTAT_WRITER, (state & RW_LOCK_READ) == 0, + (state & RW_LOCK_READ) == 0 ? 0 : RW_READERS(state)); - /* - * Record only the loops spinning and not sleeping. - */ + /* Record only the loops spinning and not sleeping. */ if (spin_cnt > sleep_cnt) - LOCKSTAT_RECORD1(LS_RW_WLOCK_SPIN, rw, (spin_cnt - sleep_cnt)); + LOCKSTAT_RECORD4(LS_RW_WLOCK_SPIN, rw, all_time - sleep_time, + LOCKSTAT_READER, (state & RW_LOCK_READ) == 0, + (state & RW_LOCK_READ) == 0 ? 0 : RW_READERS(state)); #endif + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_RW_WLOCK_ACQUIRE, rw, contested, + waittime, file, line); } /* diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5d48060..b70da5b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -3309,7 +3309,7 @@ coredump(struct thread *td) * a corefile is truncated instead of not being created, * if it is larger than the limit. */ - limit = (off_t)lim_cur(p, RLIMIT_CORE); + limit = (off_t)lim_cur(td, RLIMIT_CORE); if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) { PROC_UNLOCK(p); return (EFBIG); diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index a986590..91e8c60 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -288,6 +288,8 @@ sx_try_slock_(struct sx *sx, const char *file, int line) if (atomic_cmpset_acq_ptr(&sx->sx_lock, x, x + SX_ONE_SHARER)) { LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line); WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line); + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_SLOCK_ACQUIRE, + sx, 0, 0, file, line); curthread->td_locks++; return (1); } @@ -348,6 +350,9 @@ sx_try_xlock_(struct sx *sx, const char *file, int line) if (rval) { WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file, line); + if (!sx_recursed(sx)) + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_XLOCK_ACQUIRE, + sx, 0, 0, file, line); curthread->td_locks++; } @@ -509,9 +514,11 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file, #endif int error = 0; #ifdef KDTRACE_HOOKS + uintptr_t state; uint64_t spin_cnt = 0; uint64_t sleep_cnt = 0; int64_t sleep_time = 0; + int64_t all_time = 0; #endif if (SCHEDULER_STOPPED()) @@ -533,6 +540,10 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file, CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__, sx->lock_object.lo_name, (void *)sx->sx_lock, file, line); +#ifdef KDTRACE_HOOKS + all_time -= lockstat_nsecs(); + state = sx->sx_lock; +#endif while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) { #ifdef KDTRACE_HOOKS spin_cnt++; @@ -705,17 +716,21 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file, CTR2(KTR_LOCK, "%s: %p resuming from sleep queue", __func__, sx); } - - GIANT_RESTORE(); - if (!error) - LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_XLOCK_ACQUIRE, sx, - contested, waittime, file, line); #ifdef KDTRACE_HOOKS + all_time += lockstat_nsecs(); if (sleep_time) - LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time); + LOCKSTAT_RECORD4(LS_SX_XLOCK_BLOCK, sx, sleep_time, + LOCKSTAT_WRITER, (state & SX_LOCK_SHARED) == 0, + (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state)); if (spin_cnt > sleep_cnt) - LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt)); + LOCKSTAT_RECORD4(LS_SX_XLOCK_SPIN, sx, all_time - sleep_time, + LOCKSTAT_WRITER, (state & SX_LOCK_SHARED) == 0, + (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state)); #endif + if (!error) + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_XLOCK_ACQUIRE, sx, + contested, waittime, file, line); + GIANT_RESTORE(); return (error); } @@ -801,14 +816,21 @@ _sx_slock_hard(struct sx *sx, int opts, const char *file, int line) uintptr_t x; int error = 0; #ifdef KDTRACE_HOOKS + uintptr_t state; uint64_t spin_cnt = 0; uint64_t sleep_cnt = 0; int64_t sleep_time = 0; + int64_t all_time = 0; #endif if (SCHEDULER_STOPPED()) return (0); +#ifdef KDTRACE_HOOKS + state = sx->sx_lock; + all_time -= lockstat_nsecs(); +#endif + /* * As with rwlocks, we don't make any attempt to try to block * shared locks once there is an exclusive waiter. @@ -958,15 +980,20 @@ _sx_slock_hard(struct sx *sx, int opts, const char *file, int line) CTR2(KTR_LOCK, "%s: %p resuming from sleep queue", __func__, sx); } - if (error == 0) - LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_SLOCK_ACQUIRE, sx, - contested, waittime, file, line); #ifdef KDTRACE_HOOKS + all_time += lockstat_nsecs(); if (sleep_time) - LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time); + LOCKSTAT_RECORD4(LS_SX_SLOCK_BLOCK, sx, sleep_time, + LOCKSTAT_READER, (state & SX_LOCK_SHARED) == 0, + (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state)); if (spin_cnt > sleep_cnt) - LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt)); + LOCKSTAT_RECORD4(LS_SX_SLOCK_SPIN, sx, all_time - sleep_time, + LOCKSTAT_READER, (state & SX_LOCK_SHARED) == 0, + (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state)); #endif + if (error == 0) + LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_SLOCK_ACQUIRE, sx, + contested, waittime, file, line); GIANT_RESTORE(); return (error); } diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index dada746..15574be 100644 --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -31,6 +31,9 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/lock.h> #include <sys/module.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/resourcevar.h> #include <sys/sx.h> #include <sys/syscall.h> #include <sys/sysent.h> diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 01c61bd..eba0b60 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$"); #include <sys/timetc.h> #include <sys/timex.h> #include <sys/vdso.h> -#include <machine/atomic.h> /* * A large step happens on boot. This constant detects such steps. @@ -190,7 +189,7 @@ tc_delta(struct timehands *th) tc->tc_counter_mask); } -static u_int +static inline u_int tc_getgen(struct timehands *th) { @@ -205,7 +204,7 @@ tc_getgen(struct timehands *th) #endif } -static void +static inline void tc_setgen(struct timehands *th, u_int newgen) { diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 6cd215e..e6b0a59 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -220,13 +220,13 @@ create_thread(struct thread *td, mcontext_t *ctx, bcopy(&td->td_startcopy, &newtd->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); newtd->td_proc = td->td_proc; - newtd->td_ucred = crhold(td->td_ucred); + thread_cow_get(newtd, td); if (ctx != NULL) { /* old way to set user context */ error = set_mcontext(newtd, ctx); if (error != 0) { + thread_cow_free(newtd); thread_free(newtd); - crfree(td->td_ucred); goto fail; } } else { @@ -238,8 +238,8 @@ create_thread(struct thread *td, mcontext_t *ctx, /* Setup user TLS address and TLS pointer register. */ error = cpu_set_user_tls(newtd, tls_base); if (error != 0) { + thread_cow_free(newtd); thread_free(newtd); - crfree(td->td_ucred); goto fail; } } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index dce760c..4343b64 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -327,8 +327,7 @@ thread_reap(void) mtx_unlock_spin(&zombie_lock); while (td_first) { td_next = TAILQ_NEXT(td_first, td_slpq); - if (td_first->td_ucred) - crfree(td_first->td_ucred); + thread_cow_free(td_first); thread_free(td_first); td_first = td_next; } @@ -384,6 +383,50 @@ thread_free(struct thread *td) uma_zfree(thread_zone, td); } +void +thread_cow_get_proc(struct thread *newtd, struct proc *p) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + newtd->td_ucred = crhold(p->p_ucred); + newtd->td_limit = lim_hold(p->p_limit); + newtd->td_cowgen = p->p_cowgen; +} + +void +thread_cow_get(struct thread *newtd, struct thread *td) +{ + + newtd->td_ucred = crhold(td->td_ucred); + newtd->td_limit = lim_hold(td->td_limit); + newtd->td_cowgen = td->td_cowgen; +} + +void +thread_cow_free(struct thread *td) +{ + + if (td->td_ucred) + crfree(td->td_ucred); + if (td->td_limit) + lim_free(td->td_limit); +} + +void +thread_cow_update(struct thread *td) +{ + struct proc *p; + + p = td->td_proc; + PROC_LOCK(p); + if (td->td_ucred != p->p_ucred) + cred_update_thread(td); + if (td->td_limit != p->p_limit) + lim_update_thread(td); + td->td_cowgen = p->p_cowgen; + PROC_UNLOCK(p); +} + /* * Discard the current thread and exit from its context. * Always called with scheduler locked. @@ -521,7 +564,7 @@ thread_wait(struct proc *p) cpuset_rel(td->td_cpuset); td->td_cpuset = NULL; cpu_thread_clean(td); - crfree(td->td_ucred); + thread_cow_free(td); thread_reap(); /* check for zombie threads etc. */ } diff --git a/sys/kern/stack_protector.c b/sys/kern/stack_protector.c index b5f9973..77be64f 100644 --- a/sys/kern/stack_protector.c +++ b/sys/kern/stack_protector.c @@ -17,15 +17,14 @@ __stack_chk_fail(void) panic("stack overflow detected; backtrace may be corrupted"); } -#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) static void __stack_chk_init(void *dummy __unused) { size_t i; - long guard[__arraycount(__stack_chk_guard)]; + long guard[nitems(__stack_chk_guard)]; arc4rand(guard, sizeof(guard), 0); - for (i = 0; i < __arraycount(guard); i++) + for (i = 0; i < nitems(guard); i++) __stack_chk_guard[i] = guard[i]; } SYSINIT(stack_chk, SI_SUB_RANDOM, SI_ORDER_ANY, __stack_chk_init, NULL); diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index 6509522..4f35838 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -37,10 +37,13 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#ifdef _KERNEL #include "opt_ddb.h" #include "opt_printf.h" +#endif /* _KERNEL */ #include <sys/param.h> +#ifdef _KERNEL #include <sys/systm.h> #include <sys/lock.h> #include <sys/kdb.h> @@ -57,7 +60,9 @@ __FBSDID("$FreeBSD$"); #include <sys/syslog.h> #include <sys/cons.h> #include <sys/uio.h> +#endif #include <sys/ctype.h> +#include <sys/sbuf.h> #ifdef DDB #include <ddb/ddb.h> @@ -69,6 +74,8 @@ __FBSDID("$FreeBSD$"); */ #include <machine/stdarg.h> +#ifdef _KERNEL + #define TOCONS 0x01 #define TOTTY 0x02 #define TOLOG 0x04 @@ -1119,3 +1126,59 @@ hexdump(const void *ptr, int length, const char *hdr, int flags) printf("\n"); } } +#endif /* _KERNEL */ + +void +sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr, + int flags) +{ + int i, j, k; + int cols; + const unsigned char *cp; + char delim; + + if ((flags & HD_DELIM_MASK) != 0) + delim = (flags & HD_DELIM_MASK) >> 8; + else + delim = ' '; + + if ((flags & HD_COLUMN_MASK) != 0) + cols = flags & HD_COLUMN_MASK; + else + cols = 16; + + cp = ptr; + for (i = 0; i < length; i+= cols) { + if (hdr != NULL) + sbuf_printf(sb, "%s", hdr); + + if ((flags & HD_OMIT_COUNT) == 0) + sbuf_printf(sb, "%04x ", i); + + if ((flags & HD_OMIT_HEX) == 0) { + for (j = 0; j < cols; j++) { + k = i + j; + if (k < length) + sbuf_printf(sb, "%c%02x", delim, cp[k]); + else + sbuf_printf(sb, " "); + } + } + + if ((flags & HD_OMIT_CHARS) == 0) { + sbuf_printf(sb, " |"); + for (j = 0; j < cols; j++) { + k = i + j; + if (k >= length) + sbuf_printf(sb, " "); + else if (cp[k] >= ' ' && cp[k] <= '~') + sbuf_printf(sb, "%c", cp[k]); + else + sbuf_printf(sb, "."); + } + sbuf_printf(sb, "|"); + } + sbuf_printf(sb, "\n"); + } +} + diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 1bf78b8..070ba28 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -61,8 +61,8 @@ syscallenter(struct thread *td, struct syscall_args *sa) p = td->td_proc; td->td_pticks = 0; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); if (p->p_flag & P_TRACED) { traced = 1; PROC_LOCK(p); diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 82387c2..375bb32 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -220,8 +220,8 @@ ast(struct trapframe *framep) thread_unlock(td); PCPU_INC(cnt.v_trap); - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); if (td->td_pflags & TDP_OWEUPC && p->p_flag & P_PROFIL) { addupc_task(td, td->td_profil_addr, td->td_profil_ticks); td->td_profil_ticks = 0; diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index 410085e..aac6eb6 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -409,10 +409,8 @@ copyout_map(struct thread *td, vm_offset_t *addr, size_t sz) /* * Map somewhere after heap in process memory. */ - PROC_LOCK(td->td_proc); *addr = round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)); - PROC_UNLOCK(td->td_proc); + lim_max(td, RLIMIT_DATA)); /* round size up to page boundry */ size = (vm_size_t)round_page(sz); diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 3240a5f..3eb126b 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -382,7 +382,7 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr, */ PROC_LOCK(p); attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr + - lim_max(p, RLIMIT_DATA)); + lim_max_proc(p, RLIMIT_DATA)); PROC_UNLOCK(p); } diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 2d1e8fe..fcc9c47 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -741,7 +741,7 @@ pts_alloc(int fflags, struct thread *td, struct file *fp) PROC_UNLOCK(p); return (EAGAIN); } - ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(p, RLIMIT_NPTS)); + ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); if (!ok) { racct_sub(p, RACCT_NPTS, 1); PROC_UNLOCK(p); @@ -795,7 +795,7 @@ pts_alloc_external(int fflags, struct thread *td, struct file *fp, PROC_UNLOCK(p); return (EAGAIN); } - ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(p, RLIMIT_NPTS)); + ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); if (!ok) { racct_sub(p, RACCT_NPTS, 1); PROC_UNLOCK(p); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 3419c51..fb84330 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -189,14 +189,6 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) if (m->valid != VM_PAGE_BITS_ALL) { if (vm_pager_has_page(obj, idx, NULL, NULL)) { rv = vm_pager_get_pages(obj, &m, 1, 0); - m = vm_page_lookup(obj, idx); - if (m == NULL) { - printf( - "uiomove_object: vm_obj %p idx %jd null lookup rv %d\n", - obj, idx, rv); - VM_OBJECT_WUNLOCK(obj); - return (EIO); - } if (rv != VM_PAGER_OK) { printf( "uiomove_object: vm_obj %p idx %jd valid %x pager error %d\n", @@ -423,7 +415,7 @@ static int shm_dotruncate(struct shmfd *shmfd, off_t length) { vm_object_t object; - vm_page_t m, ma[1]; + vm_page_t m; vm_pindex_t idx, nobjsize; vm_ooffset_t delta; int base, rv; @@ -465,12 +457,10 @@ retry: VM_WAIT; VM_OBJECT_WLOCK(object); goto retry; - } else if (m->valid != VM_PAGE_BITS_ALL) { - ma[0] = m; - rv = vm_pager_get_pages(object, ma, 1, + } else if (m->valid != VM_PAGE_BITS_ALL) + rv = vm_pager_get_pages(object, &m, 1, 0); - m = vm_page_lookup(object, idx); - } else + else /* A cached page was reactivated. */ rv = VM_PAGER_OK; vm_page_lock(m); diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 88952ed..243450d 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -420,9 +420,7 @@ sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, if (cc > sb_max_adj) return (0); if (td != NULL) { - PROC_LOCK(td->td_proc); - sbsize_limit = lim_cur(td->td_proc, RLIMIT_SBSIZE); - PROC_UNLOCK(td->td_proc); + sbsize_limit = lim_cur(td, RLIMIT_SBSIZE); } else sbsize_limit = RLIM_INFINITY; if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 1efe3da..e3557ba 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -2026,10 +2026,7 @@ sendfile_readpage(vm_object_t obj, struct vnode *vp, int nd, if (vm_pager_has_page(obj, pindex, NULL, NULL)) { rv = vm_pager_get_pages(obj, &m, 1, 0); SFSTAT_INC(sf_iocnt); - m = vm_page_lookup(obj, pindex); - if (m == NULL) - error = EIO; - else if (rv != VM_PAGER_OK) { + if (rv != VM_PAGER_OK) { vm_page_lock(m); vm_page_free(m); vm_page_unlock(m); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index ef0b83c..acf9fe9 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1736,7 +1736,7 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) int i; int *fdp; struct filedesc *fdesc = td->td_proc->p_fd; - struct filedescent *fde, **fdep; + struct filedescent **fdep; void *data; socklen_t clen = control->m_len, datalen; int error, newfds; @@ -1787,7 +1787,7 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) fdp = (int *) CMSG_DATA(mtod(*controlp, struct cmsghdr *)); if (fdallocn(td, 0, fdp, newfds) != 0) { - FILEDESC_XUNLOCK(td->td_proc->p_fd); + FILEDESC_XUNLOCK(fdesc); error = EMSGSIZE; unp_freerights(fdep, newfds); m_freem(*controlp); @@ -1795,13 +1795,10 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) goto next; } for (i = 0; i < newfds; i++, fdp++) { - fde = &fdesc->fd_ofiles[*fdp]; - fde->fde_file = fdep[i]->fde_file; - filecaps_move(&fdep[i]->fde_caps, - &fde->fde_caps); - if ((flags & MSG_CMSG_CLOEXEC) != 0) - fde->fde_flags |= UF_EXCLOSE; - unp_externalize_fp(fde->fde_file); + _finstall(fdesc, fdep[i]->fde_file, *fdp, + (flags & MSG_CMSG_CLOEXEC) != 0 ? UF_EXCLOSE : 0, + &fdep[i]->fde_caps); + unp_externalize_fp(fdep[i]->fde_file); } FILEDESC_XUNLOCK(fdesc); free(fdep[0], M_FILECAPS); diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c index e9361e5..56cc6c9 100644 --- a/sys/kern/vfs_acl.c +++ b/sys/kern/vfs_acl.c @@ -406,7 +406,7 @@ sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, + error = getvnode(td, 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); @@ -425,7 +425,7 @@ sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, + error = getvnode(td, 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); @@ -480,7 +480,7 @@ sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, + error = getvnode(td, uap->filedes, cap_rights_init(&rights, CAP_ACL_DELETE), &fp); if (error == 0) { error = vacl_delete(td, fp->f_vnode, uap->type); @@ -535,7 +535,7 @@ sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) cap_rights_t rights; int error; - error = getvnode(td->td_proc->p_fd, uap->filedes, + error = getvnode(td, uap->filedes, cap_rights_init(&rights, CAP_ACL_CHECK), &fp); if (error == 0) { error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 24935ce..0f82c2b 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -226,7 +226,7 @@ sys_extattr_set_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) return (error); @@ -401,7 +401,7 @@ sys_extattr_get_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_EXTATTR_GET), &fp); if (error) return (error); @@ -545,7 +545,7 @@ sys_extattr_delete_fd(td, uap) return (error); AUDIT_ARG_TEXT(attrname); - error = getvnode(td->td_proc->p_fd, uap->fd, + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_EXTATTR_DELETE), &fp); if (error) return (error); @@ -697,7 +697,7 @@ sys_extattr_list_fd(td, uap) AUDIT_ARG_FD(uap->fd); AUDIT_ARG_VALUE(uap->attrnamespace); - error = getvnode(td->td_proc->p_fd, uap->fd, + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_EXTATTR_LIST), &fp); if (error) return (error); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 625d193..ce194f9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -173,6 +173,11 @@ static int reassignbufcalls; SYSCTL_INT(_vfs, OID_AUTO, reassignbufcalls, CTLFLAG_RW, &reassignbufcalls, 0, "Number of calls to reassignbuf"); +static u_long free_owe_inact; +SYSCTL_ULONG(_vfs, OID_AUTO, free_owe_inact, CTLFLAG_RD, &free_owe_inact, 0, + "Number of times free vnodes kept on active list due to VFS " + "owing inactivation"); + /* * Cache for the mount type id assigned to NFS. This is used for * special checks in nfs/nfs_nqlease.c and vm/vnode_pager.c. @@ -2368,11 +2373,8 @@ vholdl(struct vnode *vp) CTR2(KTR_VFS, "%s: vp %p", __func__, vp); #ifdef INVARIANTS /* getnewvnode() calls v_incr_usecount() without holding interlock. */ - if (vp->v_type != VNON || vp->v_data != NULL) { + if (vp->v_type != VNON || vp->v_data != NULL) ASSERT_VI_LOCKED(vp, "vholdl"); - VNASSERT(vp->v_holdcnt > 0 || (vp->v_iflag & VI_FREE) != 0, - vp, ("vholdl: free vnode is held")); - } #endif vp->v_holdcnt++; if ((vp->v_iflag & VI_FREE) == 0) @@ -2443,23 +2445,29 @@ vdropl(struct vnode *vp) VNASSERT(vp->v_holdcnt == 0, vp, ("vdropl: freeing when we shouldn't")); active = vp->v_iflag & VI_ACTIVE; - vp->v_iflag &= ~VI_ACTIVE; - mp = vp->v_mount; - mtx_lock(&vnode_free_list_mtx); - if (active) { - TAILQ_REMOVE(&mp->mnt_activevnodelist, vp, - v_actfreelist); - mp->mnt_activevnodelistsize--; - } - if (vp->v_iflag & VI_AGE) { - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_actfreelist); + if ((vp->v_iflag & VI_OWEINACT) == 0) { + vp->v_iflag &= ~VI_ACTIVE; + mp = vp->v_mount; + mtx_lock(&vnode_free_list_mtx); + if (active) { + TAILQ_REMOVE(&mp->mnt_activevnodelist, vp, + v_actfreelist); + mp->mnt_activevnodelistsize--; + } + if (vp->v_iflag & VI_AGE) { + TAILQ_INSERT_HEAD(&vnode_free_list, vp, + v_actfreelist); + } else { + TAILQ_INSERT_TAIL(&vnode_free_list, vp, + v_actfreelist); + } + freevnodes++; + vp->v_iflag &= ~VI_AGE; + vp->v_iflag |= VI_FREE; + mtx_unlock(&vnode_free_list_mtx); } else { - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_actfreelist); + atomic_add_long(&free_owe_inact, 1); } - freevnodes++; - vp->v_iflag &= ~VI_AGE; - vp->v_iflag |= VI_FREE; - mtx_unlock(&vnode_free_list_mtx); VI_UNLOCK(vp); return; } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index d2f0df1..9088017 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -365,8 +365,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) int error; AUDIT_ARG_FD(fd); - error = getvnode(td->td_proc->p_fd, fd, - cap_rights_init(&rights, CAP_FSTATFS), &fp); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_FSTATFS), &fp); if (error != 0) return (error); vp = fp->f_vnode; @@ -737,7 +736,7 @@ sys_fchdir(td, uap) int error; AUDIT_ARG_FD(uap->fd); - error = getvnode(fdp, uap->fd, cap_rights_init(&rights, CAP_FCHDIR), + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FCHDIR), &fp); if (error != 0) return (error); @@ -2671,8 +2670,8 @@ sys_fchflags(td, uap) AUDIT_ARG_FD(uap->fd); AUDIT_ARG_FFLAGS(uap->flags); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_FCHFLAGS), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FCHFLAGS), + &fp); if (error != 0) return (error); #ifdef AUDIT @@ -3239,8 +3238,7 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr, error = getutimes(tptr, tptrseg, ts); if (error != 0) return (error); - error = getvnode(td->td_proc->p_fd, fd, - cap_rights_init(&rights, CAP_FUTIMES), &fp); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_FUTIMES), &fp); if (error != 0) return (error); #ifdef AUDIT @@ -3275,8 +3273,7 @@ kern_futimens(struct thread *td, int fd, struct timespec *tptr, return (error); if (flags & UTIMENS_EXIT) return (0); - error = getvnode(td->td_proc->p_fd, fd, - cap_rights_init(&rights, CAP_FUTIMES), &fp); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_FUTIMES), &fp); if (error != 0) return (error); #ifdef AUDIT @@ -3470,8 +3467,7 @@ sys_fsync(td, uap) int error, lock_flags; AUDIT_ARG_FD(uap->fd); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_FSYNC), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FSYNC), &fp); if (error != 0) return (error); vp = fp->f_vnode; @@ -3894,8 +3890,7 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -4058,8 +4053,7 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, if (count > IOSIZE_MAX) return (EINVAL); auio.uio_resid = count; - error = getvnode(td->td_proc->p_fd, fd, - cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_READ), &fp); if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -4225,12 +4219,12 @@ out: * entry is held upon returning. */ int -getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp) +getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) { struct file *fp; int error; - error = fget_unlocked(fdp, fd, rightsp, &fp, NULL); + error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL); if (error != 0) return (error); @@ -4247,7 +4241,7 @@ getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp) * checking f_ops. */ if (fp->f_vnode == NULL || fp->f_ops == &badfileops) { - fdrop(fp, curthread); + fdrop(fp, td); return (EINVAL); } *fpp = fp; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 573d009..0b073b9 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -2106,19 +2106,18 @@ vn_vget_ino_gen(struct vnode *vp, vn_get_ino_t alloc, void *alloc_arg, int vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio, - const struct thread *td) + struct thread *td) { if (vp->v_type != VREG || td == NULL) return (0); - PROC_LOCK(td->td_proc); if ((uoff_t)uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { + lim_cur(td, RLIMIT_FSIZE)) { + PROC_LOCK(td->td_proc); kern_psignal(td->td_proc, SIGXFSZ); PROC_UNLOCK(td->td_proc); return (EFBIG); } - PROC_UNLOCK(td->td_proc); return (0); } diff --git a/sys/mips/conf/AR934X_BASE b/sys/mips/conf/AR934X_BASE index 7a62633..50af5f2 100644 --- a/sys/mips/conf/AR934X_BASE +++ b/sys/mips/conf/AR934X_BASE @@ -20,7 +20,7 @@ files "../atheros/files.ar71xx" hints "AR934X_BASE.hints" makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols -makeoptions MODULES_OVERRIDE="random gpio ar71xx if_gif if_gre if_bridge bridgestp usb wlan wlan_xauth wlan_acl wlan_wep wlan_tkip wlan_ccmp wlan_rssadapt wlan_amrr ath ath_ahb hwpmc" +makeoptions MODULES_OVERRIDE="random gpio ar71xx if_gif if_gre if_vlan if_bridge bridgestp usb wlan wlan_xauth wlan_acl wlan_wep wlan_tkip wlan_ccmp wlan_rssadapt wlan_amrr ath ath_ahb hwpmc ipfw ipfw_nat libalias" # makeoptions MODULES_OVERRIDE="" options DDB diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile index 84d5ef2..da3d776 100644 --- a/sys/modules/usb/Makefile +++ b/sys/modules/usb/Makefile @@ -53,7 +53,7 @@ SUBDIR += ${_dwc_otg} ehci ${_musb} ohci uhci xhci ${_uss820dci} ${_at91dci} \ ${_atmegadci} ${_avr32dci} ${_rsu} ${_rsufw} ${_saf1761otg} SUBDIR += ${_rum} ${_run} ${_runfw} ${_uath} upgt usie ural ${_zyd} ${_urtw} SUBDIR += ${_urtwn} ${_urtwnfw} -SUBDIR += atp uhid ukbd ums udbp ufm uep wsp uled +SUBDIR += atp uhid ukbd ums udbp ufm uep wsp ugold uled SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ umct umcs umodem umoscom uplcom uslcom uvisor uvscom SUBDIR += udl diff --git a/sys/modules/usb/ugold/Makefile b/sys/modules/usb/ugold/Makefile new file mode 100644 index 0000000..48af6ef --- /dev/null +++ b/sys/modules/usb/ugold/Makefile @@ -0,0 +1,13 @@ +# +# $FreeBSD$ +# + +S= ${.CURDIR}/../../.. + +.PATH: $S/dev/usb/misc + +KMOD= ugold +SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h \ + usbdevs.h ugold.c + +.include <bsd.kmod.mk> diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index faa7681..c6bcfdf 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1033,9 +1033,12 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, case IFT_ETHER: case IFT_L2VLAN: /* - * Take the interface out of promiscuous mode. + * Take the interface out of promiscuous mode, but only + * if it was promiscuous in the first place. It might + * not be if we're in the bridge_ioctl_add() error path. */ - (void) ifpromisc(ifs, 0); + if (ifs->if_flags & IFF_PROMISC) + (void) ifpromisc(ifs, 0); break; case IFT_GIF: @@ -1203,10 +1206,8 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) break; } - if (error) { + if (error) bridge_delete_member(sc, bif, 0); - free(bif, M_DEVBUF); - } return (error); } diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index fec6aa0..aa370d6 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -364,6 +364,7 @@ retry: if ((la->la_flags & LLE_VALID) && ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { bcopy(&la->ll_addr, desten, ifp->if_addrlen); + renew = 0; /* * If entry has an expiry time and it is approaching, * see if we need to send an ARP request within this @@ -371,14 +372,22 @@ retry: */ if (!(la->la_flags & LLE_STATIC) && time_uptime + la->la_preempt > la->la_expire) { - arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); + renew = 1; la->la_preempt--; } if (pflags != NULL) *pflags = la->la_flags; - error = 0; - goto done; + + if (flags & LLE_EXCLUSIVE) + LLE_WUNLOCK(la); + else + LLE_RUNLOCK(la); + + if (renew == 1) + arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); + + return (0); } if (la->la_flags & LLE_STATIC) { /* should not happen! */ diff --git a/sys/netinet/ip_encap.c b/sys/netinet/ip_encap.c index fcd048a..d3d0116 100644 --- a/sys/netinet/ip_encap.c +++ b/sys/netinet/ip_encap.c @@ -95,14 +95,14 @@ static MALLOC_DEFINE(M_NETADDR, "encap_export_host", "Export host address struct static void encap_add(struct encaptab *); static int mask_match(const struct encaptab *, const struct sockaddr *, const struct sockaddr *); -static void encap_fillarg(struct mbuf *, const struct encaptab *); +static void encap_fillarg(struct mbuf *, void *); /* * All global variables in ip_encap.c are locked using encapmtx. */ static struct mtx encapmtx; MTX_SYSINIT(encapmtx, &encapmtx, "encapmtx", MTX_DEF); -LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(encaptab); +static LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(encaptab); /* * We currently keey encap_init() for source code compatibility reasons -- @@ -122,12 +122,12 @@ encap4_input(struct mbuf **mp, int *offp, int proto) struct sockaddr_in s, d; const struct protosw *psw; struct encaptab *ep, *match; + void *arg; int matchprio, off, prio; m = *mp; off = *offp; ip = mtod(m, struct ip *); - *mp = NULL; bzero(&s, sizeof(s)); s.sin_family = AF_INET; @@ -138,6 +138,8 @@ encap4_input(struct mbuf **mp, int *offp, int proto) d.sin_len = sizeof(struct sockaddr_in); d.sin_addr = ip->ip_dst; + arg = NULL; + psw = NULL; match = NULL; matchprio = 0; mtx_lock(&encapmtx); @@ -182,14 +184,16 @@ encap4_input(struct mbuf **mp, int *offp, int proto) match = ep; } } + if (match != NULL) { + psw = match->psw; + arg = match->arg; + } mtx_unlock(&encapmtx); - if (match) { + if (match != NULL) { /* found a match, "match" has the best one */ - psw = match->psw; - if (psw && psw->pr_input) { - encap_fillarg(m, match); - *mp = m; + if (psw != NULL && psw->pr_input != NULL) { + encap_fillarg(m, arg); (*psw->pr_input)(mp, offp, proto); } else m_freem(m); @@ -197,7 +201,6 @@ encap4_input(struct mbuf **mp, int *offp, int proto) } /* last resort: inject to raw socket */ - *mp = m; return (rip_input(mp, offp, proto)); } #endif @@ -211,6 +214,7 @@ encap6_input(struct mbuf **mp, int *offp, int proto) struct sockaddr_in6 s, d; const struct protosw *psw; struct encaptab *ep, *match; + void *arg; int prio, matchprio; ip6 = mtod(m, struct ip6_hdr *); @@ -224,6 +228,8 @@ encap6_input(struct mbuf **mp, int *offp, int proto) d.sin6_len = sizeof(struct sockaddr_in6); d.sin6_addr = ip6->ip6_dst; + arg = NULL; + psw = NULL; match = NULL; matchprio = 0; mtx_lock(&encapmtx); @@ -251,17 +257,20 @@ encap6_input(struct mbuf **mp, int *offp, int proto) match = ep; } } + if (match != NULL) { + psw = match->psw; + arg = match->arg; + } mtx_unlock(&encapmtx); - if (match) { + if (match != NULL) { /* found a match */ - psw = match->psw; - if (psw && psw->pr_input) { - encap_fillarg(m, match); + if (psw != NULL && psw->pr_input != NULL) { + encap_fillarg(m, arg); return (*psw->pr_input)(mp, offp, proto); } else { m_freem(m); - return IPPROTO_DONE; + return (IPPROTO_DONE); } } @@ -440,14 +449,16 @@ mask_match(const struct encaptab *ep, const struct sockaddr *sp, } static void -encap_fillarg(struct mbuf *m, const struct encaptab *ep) +encap_fillarg(struct mbuf *m, void *arg) { struct m_tag *tag; - tag = m_tag_get(PACKET_TAG_ENCAP, sizeof (void*), M_NOWAIT); - if (tag) { - *(void**)(tag+1) = ep->arg; - m_tag_prepend(m, tag); + if (arg != NULL) { + tag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT); + if (tag != NULL) { + *(void**)(tag+1) = arg; + m_tag_prepend(m, tag); + } } } diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 21add43..a64e7f9 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -1109,7 +1109,8 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) * not be changed. */ SCTP_RTALLOC((sctp_route_t *) & net->ro, - stcb->sctp_ep->def_vrf_id); + stcb->sctp_ep->def_vrf_id, + stcb->sctp_ep->fibnum); if (net->ro.ro_rt == NULL) continue; @@ -1328,6 +1329,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, { uint32_t status; int pending_delete_queued = 0; + int last; /* see if peer supports ASCONF */ if (stcb->asoc.asconf_supported == 0) { @@ -1337,15 +1339,21 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, * if this is deleting the last address from the assoc, mark it as * pending. */ - if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending && - (sctp_local_addr_count(stcb) < 2)) { - /* set the pending delete info only */ - stcb->asoc.asconf_del_pending = 1; - stcb->asoc.asconf_addr_del_pending = ifa; - atomic_add_int(&ifa->refcount, 1); - SCTPDBG(SCTP_DEBUG_ASCONF2, - "asconf_queue_add: mark delete last address pending\n"); - return (-1); + if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending) { + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { + last = (sctp_local_addr_count(stcb) == 0); + } else { + last = (sctp_local_addr_count(stcb) == 1); + } + if (last) { + /* set the pending delete info only */ + stcb->asoc.asconf_del_pending = 1; + stcb->asoc.asconf_addr_del_pending = ifa; + atomic_add_int(&ifa->refcount, 1); + SCTPDBG(SCTP_DEBUG_ASCONF2, + "asconf_queue_add: mark delete last address pending\n"); + return (-1); + } } /* queue an asconf parameter */ status = sctp_asconf_queue_mgmt(stcb, ifa, type); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 89047cb..c6bea83 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -186,7 +186,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "No listener"); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); } goto outnow; @@ -1484,7 +1484,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, net->port); if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 2; @@ -1694,7 +1694,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, */ op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); return (NULL); } @@ -2572,7 +2572,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, tim = now.tv_usec - cookie->time_entered.tv_usec; scm->time_usec = htonl(tim); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, - mflowtype, mflowid, + mflowtype, mflowid, l_inp->fibnum, vrf_id, port); return (NULL); } @@ -2676,8 +2676,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, /* still no TCB... must be bad cookie-echo */ return (NULL); } - if ((*netp != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (*netp != NULL) { (*netp)->flowtype = mflowtype; + (*netp)->flowid = mflowid; } /* * Ok, we built an association so confirm the address we sent the @@ -2794,6 +2795,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, inp->partial_delivery_point = (*inp_p)->partial_delivery_point; inp->sctp_context = (*inp_p)->sctp_context; inp->local_strreset_support = (*inp_p)->local_strreset_support; + inp->fibnum = (*inp_p)->fibnum; inp->inp_starting_point_for_iterator = NULL; /* * copy in the authentication parameters from the @@ -4404,7 +4406,7 @@ __attribute__((noinline)) struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { struct sctp_association *asoc; @@ -4568,7 +4570,7 @@ __attribute__((noinline)) msg); /* no association, so it's out of the blue... */ sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); *offset = length; if (locked_tcb) { @@ -4612,7 +4614,7 @@ __attribute__((noinline)) msg); sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); return (NULL); } @@ -5622,7 +5624,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt uint8_t compute_crc, #endif uint8_t ecn_bits, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { uint32_t high_tsn; @@ -5661,8 +5663,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt net->port = port; } #endif - if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (net != NULL) { net->flowtype = mflowtype; + net->flowid = mflowid; } if ((inp != NULL) && (stcb != NULL)) { sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); @@ -5691,8 +5694,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt net->port = port; } #endif - if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (net != NULL) { net->flowtype = mflowtype; + net->flowid = mflowid; } if (inp == NULL) { SCTP_STAT_INCR(sctps_noport); @@ -5701,7 +5705,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { sctp_send_shutdown_complete2(src, dst, sh, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); goto out; } @@ -5716,7 +5720,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt "Out of the blue"); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); } } @@ -5775,7 +5779,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); goto out; } @@ -5786,7 +5790,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt stcb = sctp_process_control(m, iphlen, &offset, length, src, dst, sh, ch, inp, stcb, &net, &fwd_tsn_seen, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); if (stcb) { /* @@ -5827,7 +5831,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); goto out; } @@ -5899,7 +5903,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); goto out; /* sa_ignore NOTREACHED */ @@ -6023,6 +6027,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) #endif uint32_t mflowid; uint8_t mflowtype; + uint16_t fibnum; iphlen = off; if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { @@ -6048,6 +6053,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) (int)m->m_pkthdr.csum_flags, CSUM_BITS); mflowid = m->m_pkthdr.flowid; mflowtype = M_HASHTYPE_GET(m); + fibnum = M_GETFIB(m); SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); /* Get IP, SCTP, and first chunk header together in the first mbuf. */ @@ -6107,7 +6113,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) compute_crc, #endif ecn_bits, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); out: if (m) { diff --git a/sys/netinet/sctp_input.h b/sys/netinet/sctp_input.h index 0c3f8a5..148864b 100644 --- a/sys/netinet/sctp_input.h +++ b/sys/netinet/sctp_input.h @@ -45,7 +45,7 @@ sctp_common_input_processing(struct mbuf **, int, int, int, uint8_t, #endif uint8_t, - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); struct sctp_stream_reset_request * diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 140f341..bae67f0 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -413,13 +413,8 @@ typedef struct callout sctp_os_timer_t; typedef struct route sctp_route_t; typedef struct rtentry sctp_rtentry_t; -/* - * XXX multi-FIB support was backed out in r179783 and it seems clear that the - * VRF support as currently in FreeBSD is not ready to support multi-FIB. - * It might be best to implement multi-FIB support for both v4 and v6 indepedent - * of VRFs and leave those to a real MPLS stack. - */ -#define SCTP_RTALLOC(ro, vrf_id) rtalloc_ign((struct route *)ro, 0UL) +#define SCTP_RTALLOC(ro, vrf_id, fibnum) \ + rtalloc_ign_fib((struct route *)ro, 0UL, fibnum) /* Future zero copy wakeup/send function */ #define SCTP_ZERO_COPY_EVENT(inp, so) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 515ee13..3ef837c 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3389,7 +3389,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp, /* * Need a route to cache. */ - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } if (ro->ro_rt == NULL) { return (NULL); @@ -4170,7 +4170,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_free_ifa(_lsrc); } else { ip->ip_src = over_addr->sin.sin_addr; - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } } if (port) { @@ -4484,7 +4484,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_free_ifa(_lsrc); } else { lsa6->sin6_addr = over_addr->sin6.sin6_addr; - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } (void)sa6_recoverscope(sin6); } @@ -5511,7 +5511,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Address added"); sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); return; } @@ -5530,7 +5530,7 @@ do_a_abort: } sctp_send_abort(init_pkt, iphlen, src, dst, sh, init_chk->init.initiate_tag, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); return; } @@ -7985,6 +7985,7 @@ again_one_more_time: } else { r_mtu = mtu; } + error = 0; /************************/ /* ASCONF transmission */ /************************/ @@ -8108,6 +8109,12 @@ again_one_more_time: * it is used to do appropriate * source address selection. */ + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + hbflag = 0; if ((error = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, outchain, auth_offset, auth, @@ -8118,21 +8125,18 @@ again_one_more_time: net->port, NULL, 0, 0, so_locked))) { - if (error == ENOBUFS) { - asoc->ifp_had_enobuf = 1; - SCTP_STAT_INCR(sctps_lowlevelerr); - } + /* + * error, we could not + * output + */ + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; + if (error == ENOBUFS) { + asoc->ifp_had_enobuf = 1; + SCTP_STAT_INCR(sctps_lowlevelerr); } - hbflag = 0; /* error, could not output */ if (error == EHOSTUNREACH) { /* @@ -8143,17 +8147,10 @@ again_one_more_time: sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; - continue; - } else - asoc->ifp_had_enobuf = 0; - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; + break; } else { - net->last_sent_time = *now; + asoc->ifp_had_enobuf = 0; } - hbflag = 0; /* * increase the number we sent, if a * cookie is sent we don't tell them @@ -8186,6 +8183,10 @@ again_one_more_time: } } } + if (error != 0) { + /* try next net */ + continue; + } /************************/ /* Control transmission */ /************************/ @@ -8382,6 +8383,15 @@ again_one_more_time: sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net); cookie = 0; } + /* Only HB or ASCONF advances time */ + if (hbflag) { + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + hbflag = 0; + } if ((error = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, outchain, @@ -8393,23 +8403,17 @@ again_one_more_time: net->port, NULL, 0, 0, so_locked))) { - if (error == ENOBUFS) { - asoc->ifp_had_enobuf = 1; - SCTP_STAT_INCR(sctps_lowlevelerr); - } + /* + * error, we could not + * output + */ + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - /* error, could not output */ - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; + if (error == ENOBUFS) { + asoc->ifp_had_enobuf = 1; + SCTP_STAT_INCR(sctps_lowlevelerr); } if (error == EHOSTUNREACH) { /* @@ -8420,19 +8424,9 @@ again_one_more_time: sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; - continue; - } else + break; + } else { asoc->ifp_had_enobuf = 0; - /* Only HB or ASCONF advances time */ - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; } /* * increase the number we sent, if a @@ -8466,6 +8460,10 @@ again_one_more_time: } } } + if (error != 0) { + /* try next net */ + continue; + } /* JRI: if dest is in PF state, do not send data to it */ if ((asoc->sctp_cmt_on_off > 0) && (net != stcb->asoc.alternate) && @@ -8720,6 +8718,14 @@ no_data_fill: */ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } + if (bundle_at || hbflag) { + /* For data/asconf and hb set time */ + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + } /* Now send it, if there is anything to send :> */ if ((error = sctp_lowlevel_chunk_output(inp, stcb, @@ -8738,23 +8744,13 @@ no_data_fill: 0, 0, so_locked))) { /* error, we could not output */ - if (error == ENOBUFS) { - SCTP_STAT_INCR(sctps_lowlevelerr); - asoc->ifp_had_enobuf = 1; - } + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; + if (error == ENOBUFS) { + SCTP_STAT_INCR(sctps_lowlevelerr); + asoc->ifp_had_enobuf = 1; } if (error == EHOSTUNREACH) { /* @@ -8779,16 +8775,6 @@ no_data_fill: endoutchain = NULL; auth = NULL; auth_offset = 0; - if (bundle_at || hbflag) { - /* For data/asconf and hb set time */ - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - } if (!no_out_cnt) { *num_out += (ctl_cnt + bundle_at); } @@ -10853,7 +10839,7 @@ static void sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, uint8_t type, struct mbuf *cause, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { struct mbuf *o_pak; @@ -10933,6 +10919,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, SCTP_BUF_RESV_UF(mout, max_linkhdr); SCTP_BUF_LEN(mout) = len; SCTP_BUF_NEXT(mout) = cause; + M_SETFIB(mout, fibnum); mout->m_pkthdr.flowid = mflowid; M_HASHTYPE_SET(mout, mflowtype); #ifdef INET @@ -11120,11 +11107,11 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, void sctp_send_shutdown_complete2(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { sctp_send_resp_msg(src, dst, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); } @@ -11943,7 +11930,7 @@ skip_stuff: void sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, struct mbuf *cause, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { /* Don't respond to an ABORT with an ABORT. */ @@ -11953,7 +11940,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockadd return; } sctp_send_resp_msg(src, dst, sh, vtag, SCTP_ABORT_ASSOCIATION, cause, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); return; } @@ -11961,11 +11948,11 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockadd void sctp_send_operr_to(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, struct mbuf *cause, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { sctp_send_resp_msg(src, dst, sh, vtag, SCTP_OPERATION_ERROR, cause, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); return; } diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index 8789df9..8e45e5c 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -117,7 +117,7 @@ void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int); void sctp_send_shutdown_complete2(struct sockaddr *, struct sockaddr *, struct sctphdr *, - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); void sctp_send_asconf(struct sctp_tcb *, struct sctp_nets *, int addr_locked); @@ -187,13 +187,13 @@ sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t, void sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, uint32_t, struct mbuf *, - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); void sctp_send_operr_to(struct sockaddr *, struct sockaddr *, struct sctphdr *, uint32_t, struct mbuf *, - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); #endif /* _KERNEL || __Userspace__ */ diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 6fcb6d2..541d4ca 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -2485,6 +2485,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable); inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable); inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable); + inp->fibnum = so->so_fibnum; /* init the small hash table we use to track asocid <-> tcb */ inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark); if (inp->sctp_asocidhash == NULL) { @@ -3949,7 +3950,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, sin6->sin6_scope_id = 0; } #endif - SCTP_RTALLOC((sctp_route_t *) & net->ro, stcb->asoc.vrf_id); + SCTP_RTALLOC((sctp_route_t *) & net->ro, + stcb->asoc.vrf_id, + stcb->sctp_ep->fibnum); if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { /* Get source address */ diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 963b89f..f5ede2a 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -430,6 +430,7 @@ struct sctp_inpcb { struct mtx inp_rdata_mtx; int32_t refcount; uint32_t def_vrf_id; + uint16_t fibnum; uint32_t total_sends; uint32_t total_recvs; uint32_t last_abort_code; diff --git a/sys/netinet/sctp_syscalls.c b/sys/netinet/sctp_syscalls.c index 28b4445..71e2f72 100644 --- a/sys/netinet/sctp_syscalls.c +++ b/sys/netinet/sctp_syscalls.c @@ -277,6 +277,10 @@ sys_sctp_generic_sendmsg (td, uap) auio.uio_td = td; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; +#ifdef KTRACE + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); +#endif /* KTRACE */ len = auio.uio_resid = uap->mlen; CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL, @@ -400,6 +404,10 @@ sys_sctp_generic_sendmsg_iov(td, uap) goto sctp_bad; } } +#ifdef KTRACE + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); +#endif /* KTRACE */ len = auio.uio_resid; CURVNET_SET(so->so_vnet); error = sctp_lower_sosend(so, to, &auio, diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 2a59e13..907412c 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -2464,9 +2464,9 @@ flags_out: } /* get flags for PMTU */ if (net->dest_state & SCTP_ADDR_NO_PMTUD) { - paddrp->spp_flags |= SPP_PMTUD_ENABLE; - } else { paddrp->spp_flags |= SPP_PMTUD_DISABLE; + } else { + paddrp->spp_flags |= SPP_PMTUD_ENABLE; } if (net->dscp & 0x01) { paddrp->spp_dscp = net->dscp & 0xfc; @@ -5678,16 +5678,23 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } if ((stcb != NULL) && (net != NULL)) { - if ((net != stcb->asoc.primary_destination) && - (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) { - /* Ok we need to set it */ - if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) { - if ((stcb->asoc.alternate) && - (!(net->dest_state & SCTP_ADDR_PF)) && - (net->dest_state & SCTP_ADDR_REACHABLE)) { - sctp_free_remote_addr(stcb->asoc.alternate); - stcb->asoc.alternate = NULL; + if (net != stcb->asoc.primary_destination) { + if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { + /* Ok we need to set it */ + if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) { + if ((stcb->asoc.alternate) && + (!(net->dest_state & SCTP_ADDR_PF)) && + (net->dest_state & SCTP_ADDR_REACHABLE)) { + sctp_free_remote_addr(stcb->asoc.alternate); + stcb->asoc.alternate = NULL; + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; } } } else { @@ -6712,7 +6719,20 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) size_t optsize = 0; void *p; int error = 0; + struct sctp_inpcb *inp; + if ((sopt->sopt_level == SOL_SOCKET) && + (sopt->sopt_name == SO_SETFIB)) { + inp = (struct sctp_inpcb *)so->so_pcb; + if (inp == NULL) { + SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS); + return (EINVAL); + } + SCTP_INP_WLOCK(inp); + inp->fibnum = so->so_fibnum; + SCTP_INP_WUNLOCK(inp); + return (0); + } if (sopt->sopt_level != IPPROTO_SCTP) { /* wrong proto level... send back up to IP */ #ifdef INET6 diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 31d93dd..ae1b3eb 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -178,6 +178,7 @@ extern struct pr_usrreqs sctp_usrreqs; if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ (void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ (void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ + (void)SCTP_OS_TIMER_STOP(&(__net)->hb_timer.timer); \ if ((__net)->ro.ro_rt) { \ RTFREE((__net)->ro.ro_rt); \ (__net)->ro.ro_rt = NULL; \ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 24110dd..c25ec39 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -3895,7 +3895,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; } sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, vrf_id, port); if (stcb != NULL) { /* Ok, now lets free it */ @@ -4051,7 +4051,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_inpcb *inp, struct mbuf *cause, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) { struct sctp_chunkhdr *ch, chunk_buf; @@ -4093,7 +4093,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, return; case SCTP_SHUTDOWN_ACK: sctp_send_shutdown_complete2(src, dst, sh, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); return; default: @@ -4107,7 +4107,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && (contains_init_chunk == 0))) { sctp_send_abort(m, iphlen, src, dst, sh, 0, cause, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); } } diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index 2ffbc2a..7df0a6c 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -208,7 +208,7 @@ sctp_handle_ootb(struct mbuf *, int, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, struct sctp_inpcb *, struct mbuf *, - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); int diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index a64e403..d992492 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -347,11 +347,12 @@ tcp_timer_2msl(void *xtp) tp = tcp_close(tp); } else { if (tp->t_state != TCPS_TIME_WAIT && - ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) - callout_reset_on(&tp->t_timers->tt_2msl, - TP_KEEPINTVL(tp), tcp_timer_2msl, tp, - inp_to_cpuid(inp)); - else + ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) { + if (!callout_reset(&tp->t_timers->tt_2msl, + TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) { + tp->t_timers->tt_flags &= ~TT_2MSL_RST; + } + } else tp = tcp_close(tp); } @@ -431,11 +432,14 @@ tcp_timer_keep(void *xtp) tp->rcv_nxt, tp->snd_una - 1, 0); free(t_template, M_TEMP); } - callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), - tcp_timer_keep, tp, inp_to_cpuid(inp)); - } else - callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), - tcp_timer_keep, tp, inp_to_cpuid(inp)); + if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), + tcp_timer_keep, tp)) { + tp->t_timers->tt_flags &= ~TT_KEEP_RST; + } + } else if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), + tcp_timer_keep, tp)) { + tp->t_timers->tt_flags &= ~TT_KEEP_RST; + } #ifdef TCPDEBUG if (inp->inp_socket->so_options & SO_DEBUG) @@ -810,6 +814,7 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) timeout_t *f_callout; struct inpcb *inp = tp->t_inpcb; int cpu = inp_to_cpuid(inp); + uint32_t f_reset; #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE) @@ -823,38 +828,49 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) case TT_DELACK: t_callout = &tp->t_timers->tt_delack; f_callout = tcp_timer_delack; + f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; f_callout = tcp_timer_rexmt; + f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; f_callout = tcp_timer_persist; + f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; f_callout = tcp_timer_keep; + f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; f_callout = tcp_timer_2msl; + f_reset = TT_2MSL_RST; break; default: panic("tp %p bad timer_type %#x", tp, timer_type); } if (delta == 0) { if ((tp->t_timers->tt_flags & timer_type) && - callout_stop(t_callout)) { - tp->t_timers->tt_flags &= ~timer_type; + callout_stop(t_callout) && + (tp->t_timers->tt_flags & f_reset)) { + tp->t_timers->tt_flags &= ~(timer_type | f_reset); } } else { if ((tp->t_timers->tt_flags & timer_type) == 0) { - tp->t_timers->tt_flags |= timer_type; + tp->t_timers->tt_flags |= (timer_type | f_reset); callout_reset_on(t_callout, delta, f_callout, tp, cpu); } else { /* Reset already running callout on the same CPU. */ - callout_reset(t_callout, delta, f_callout, tp); + if (!callout_reset(t_callout, delta, f_callout, tp)) { + /* + * Callout not cancelled, consider it as not + * properly restarted. */ + tp->t_timers->tt_flags &= ~f_reset; + } } } } @@ -891,6 +907,7 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) { struct callout *t_callout; timeout_t *f_callout; + uint32_t f_reset; tp->t_timers->tt_flags |= TT_STOPPED; @@ -898,30 +915,36 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) case TT_DELACK: t_callout = &tp->t_timers->tt_delack; f_callout = tcp_timer_delack_discard; + f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; f_callout = tcp_timer_rexmt_discard; + f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; f_callout = tcp_timer_persist_discard; + f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; f_callout = tcp_timer_keep_discard; + f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; f_callout = tcp_timer_2msl_discard; + f_reset = TT_2MSL_RST; break; default: panic("tp %p bad timer_type %#x", tp, timer_type); } if (tp->t_timers->tt_flags & timer_type) { - if (callout_stop(t_callout)) { - tp->t_timers->tt_flags &= ~timer_type; + if (callout_stop(t_callout) && + (tp->t_timers->tt_flags & f_reset)) { + tp->t_timers->tt_flags &= ~(timer_type | f_reset); } else { /* * Can't stop the callout, defer tcpcb actual deletion diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 02a7782..dbb8aee 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -160,6 +160,12 @@ struct tcp_timer { #define TT_2MSL 0x0010 #define TT_MASK (TT_DELACK|TT_REXMT|TT_PERSIST|TT_KEEP|TT_2MSL) +#define TT_DELACK_RST 0x0100 +#define TT_REXMT_RST 0x0200 +#define TT_PERSIST_RST 0x0400 +#define TT_KEEP_RST 0x0800 +#define TT_2MSL_RST 0x1000 + #define TT_STOPPED 0x00010000 #define TP_KEEPINIT(tp) ((tp)->t_keepinit ? (tp)->t_keepinit : tcp_keepinit) diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 54c65b6..009c47f 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -84,6 +84,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) #endif uint32_t mflowid; uint8_t mflowtype; + uint16_t fibnum; iphlen = *offp; if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) { @@ -109,6 +110,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) (int)m->m_pkthdr.csum_flags, CSUM_BITS); mflowid = m->m_pkthdr.flowid; mflowtype = M_HASHTYPE_GET(m); + fibnum = M_GETFIB(m); SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); /* Get IP, SCTP, and first chunk header together in the first mbuf. */ @@ -169,7 +171,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) compute_crc, #endif ecn_bits, - mflowtype, mflowid, + mflowtype, mflowid, fibnum, vrf_id, port); out: if (m) { diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 1e70fb2..b6c6a6a 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -7714,14 +7714,6 @@ key_sa_chgstate(struct secasvar *sav, u_int8_t state) } } -void -key_sa_stir_iv(struct secasvar *sav) -{ - - IPSEC_ASSERT(sav->iv != NULL, ("null IV")); - key_randomfill(sav->iv, sav->ivlen); -} - /* * Take one of the kernel's security keys and convert it into a PF_KEY * structure within an mbuf, suitable for sending up to a waiting diff --git a/sys/netipsec/key.h b/sys/netipsec/key.h index 29abb80..82811be 100644 --- a/sys/netipsec/key.h +++ b/sys/netipsec/key.h @@ -105,7 +105,6 @@ extern void key_init(void); extern void key_destroy(void); #endif extern void key_sa_recordxfer(struct secasvar *, struct mbuf *); -extern void key_sa_stir_iv(struct secasvar *); #ifdef IPSEC_NAT_T u_int16_t key_portfromsaddr(struct sockaddr *); #define KEY_PORTFROMSADDR(saddr) \ diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 3f210c2..384f565 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -76,7 +76,6 @@ struct pf_fragment_cmp { uint32_t frc_id; sa_family_t frc_af; uint8_t frc_proto; - uint8_t frc_direction; }; struct pf_fragment { @@ -86,7 +85,6 @@ struct pf_fragment { #define fr_id fr_key.frc_id #define fr_af fr_key.frc_af #define fr_proto fr_key.frc_proto -#define fr_direction fr_key.frc_direction RB_ENTRY(pf_fragment) fr_entry; TAILQ_ENTRY(pf_fragment) frag_next; @@ -157,7 +155,7 @@ static struct mbuf *pf_fragcache(struct mbuf **, struct ip*, #endif /* INET */ #ifdef INET6 static int pf_reassemble6(struct mbuf **, struct ip6_hdr *, - struct ip6_frag *, uint16_t, uint16_t, int, u_short *); + struct ip6_frag *, uint16_t, uint16_t, u_short *); static void pf_scrub_ip6(struct mbuf **, uint8_t); #endif /* INET6 */ @@ -178,7 +176,6 @@ pf_ip2key(struct ip *ip, int dir, struct pf_fragment_cmp *key) key->frc_af = AF_INET; key->frc_proto = ip->ip_p; key->frc_id = ip->ip_id; - key->frc_direction = dir; } #endif /* INET */ @@ -663,7 +660,7 @@ pf_reassemble(struct mbuf **m0, struct ip *ip, int dir, u_short *reason) #ifdef INET6 static int pf_reassemble6(struct mbuf **m0, struct ip6_hdr *ip6, struct ip6_frag *fraghdr, - uint16_t hdrlen, uint16_t extoff, int dir, u_short *reason) + uint16_t hdrlen, uint16_t extoff, u_short *reason) { struct mbuf *m = *m0; struct pf_frent *frent; @@ -697,7 +694,6 @@ pf_reassemble6(struct mbuf **m0, struct ip6_hdr *ip6, struct ip6_frag *fraghdr, /* Only the first fragment's protocol is relevant. */ key.frc_proto = 0; key.frc_id = fraghdr->ip6f_ident; - key.frc_direction = dir; if ((frag = pf_fillup_fragment(&key, frent, reason)) == NULL) { PF_FRAG_UNLOCK(); @@ -823,6 +819,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff, (*frag)->fr_max = 0; (*frag)->fr_src.v4 = h->ip_src; (*frag)->fr_dst.v4 = h->ip_dst; + (*frag)->fr_af = AF_INET; + (*frag)->fr_proto = h->ip_p; (*frag)->fr_id = h->ip_id; (*frag)->fr_timeout = time_uptime; @@ -1553,7 +1551,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, off += sizeof(frag); /* Returns PF_DROP or *m0 is NULL or completely reassembled mbuf. */ - if (pf_reassemble6(m0, h, &frag, off, extoff, dir, reason) != PF_PASS) + if (pf_reassemble6(m0, h, &frag, off, extoff, reason) != PF_PASS) return (PF_DROP); m = *m0; if (m == NULL) diff --git a/sys/ofed/drivers/infiniband/core/umem.c b/sys/ofed/drivers/infiniband/core/umem.c index cdd2e67..5f4465f 100644 --- a/sys/ofed/drivers/infiniband/core/umem.c +++ b/sys/ofed/drivers/infiniband/core/umem.c @@ -272,7 +272,7 @@ struct ib_umem *ib_umem_get_ex(struct ib_ucontext *context, unsigned long addr, PROC_LOCK(proc); if (ptoa(npages + pmap_wired_count(vm_map_pmap(&proc->p_vmspace->vm_map))) > - lim_cur(proc, RLIMIT_MEMLOCK)) { + lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); kfree(umem); return ERR_PTR(-ENOMEM); diff --git a/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c b/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c index 0cdebaf..ad5818e 100644 --- a/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -553,7 +553,8 @@ out: proc = curproc; pmap = vm_map_pmap(&proc->p_vmspace->vm_map); PROC_LOCK(proc); - if (ptoa(pmap_wired_count(pmap) + 1) > lim_cur(proc, RLIMIT_MEMLOCK)) { + if (ptoa(pmap_wired_count(pmap) + 1) > + lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); ret = -ENOMEM; goto out; diff --git a/sys/ofed/include/linux/file.h b/sys/ofed/include/linux/file.h index f1a7398..e2cebab 100644 --- a/sys/ofed/include/linux/file.h +++ b/sys/ofed/include/linux/file.h @@ -33,6 +33,7 @@ #include <sys/file.h> #include <sys/filedesc.h> #include <sys/refcount.h> +#include <sys/capsicum.h> #include <sys/proc.h> #include <linux/fs.h> @@ -46,10 +47,11 @@ extern struct fileops linuxfileops; static inline struct linux_file * linux_fget(unsigned int fd) { + cap_rights_t rights; struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, &file, - NULL) != 0) { + if (fget_unlocked(curthread->td_proc->p_fd, fd, + cap_rights_init(&rights), &file, NULL) != 0) { return (NULL); } return (struct linux_file *)file->f_data; @@ -71,10 +73,11 @@ fput(struct linux_file *filp) static inline void put_unused_fd(unsigned int fd) { + cap_rights_t rights; struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, &file, - NULL) != 0) { + if (fget_unlocked(curthread->td_proc->p_fd, fd, + cap_rights_init(&rights), &file, NULL) != 0) { return; } /* @@ -91,10 +94,11 @@ put_unused_fd(unsigned int fd) static inline void fd_install(unsigned int fd, struct linux_file *filp) { + cap_rights_t rights; struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, &file, - NULL) != 0) { + if (fget_unlocked(curthread->td_proc->p_fd, fd, + cap_rights_init(&rights), &file, NULL) != 0) { file = NULL; } filp->_file = file; diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c index 0ecdeb3..d084b77 100644 --- a/sys/opencrypto/crypto.c +++ b/sys/opencrypto/crypto.c @@ -1181,8 +1181,8 @@ crypto_kdone(struct cryptkop *krp) /* XXX: What if driver is loaded in the meantime? */ if (krp->krp_hid < crypto_drivers_num) { cap = &crypto_drivers[krp->krp_hid]; + KASSERT(cap->cc_koperations > 0, ("cc_koperations == 0")); cap->cc_koperations--; - KASSERT(cap->cc_koperations >= 0, ("cc_koperations < 0")); if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) crypto_remove(cap); } diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES index 974c91b..9bfe6a9 100644 --- a/sys/powerpc/conf/NOTES +++ b/sys/powerpc/conf/NOTES @@ -3,6 +3,28 @@ # This file contains machine dependent kernel configuration notes. For # machine independent notes, look in /sys/conf/NOTES. +# +# Enable the kernel DTrace hooks which are required to load the DTrace +# kernel modules. +# +options KDTRACE_HOOKS + +# DTrace core +# NOTE: introduces CDDL-licensed components into the kernel +#device dtrace + +# DTrace modules +#device dtrace_lockstat +#device dtrace_profile +#device dtrace_sdt +#device dtrace_fbt +#device dtrace_systrace +#device dtrace_prototype +#device dtnfscl +#device dtmalloc + +# Alternatively include all the DTrace modules +#device dtraceall ##################################################################### diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index 0ceb170..bfbd94d 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -196,8 +196,8 @@ trap(struct trapframe *frame) if (user) { td->td_pticks = 0; td->td_frame = frame; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); /* User Mode Traps */ switch (type) { diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index 2e86842..c006b90 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/filedesc.h> +#include <sys/capsicum.h> #include <sys/ipc.h> #include <sys/mount.h> #include <sys/proc.h> @@ -894,6 +895,7 @@ audit_arg_fcntl_rights(uint32_t fcntlrights) void audit_sysclose(struct thread *td, int fd) { + cap_rights_t rights; struct kaudit_record *ar; struct vnode *vp; struct file *fp; @@ -906,7 +908,7 @@ audit_sysclose(struct thread *td, int fd) audit_arg_fd(fd); - if (getvnode(td->td_proc->p_fd, fd, 0, &fp) != 0) + if (getvnode(td, fd, cap_rights_init(&rights), &fp) != 0) return; vp = fp->f_vnode; diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index b4f0e27..e9917e5 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -277,8 +277,8 @@ trap(struct trapframe *tf) td->td_pticks = 0; td->td_frame = tf; addr = tf->tf_tpc; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); + if (td->td_cowgen != p->p_cowgen) + thread_cow_update(td); switch (tf->tf_type) { case T_DATA_MISS: diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index eca30ff..fe95111 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -83,8 +83,8 @@ struct filedesc { int fd_lastfile; /* high-water mark of fd_ofiles */ int fd_freefile; /* approx. next free file */ u_short fd_cmask; /* mask for file creation */ - u_short fd_refcnt; /* thread reference count */ - u_short fd_holdcnt; /* hold count on structure + mutex */ + int fd_refcnt; /* thread reference count */ + int fd_holdcnt; /* hold count on structure + mutex */ struct sx fd_sx; /* protects members of this struct */ struct kqlist fd_kqlist; /* list of kqueues on this filedesc */ int fd_holdleaderscount; /* block fdfree() for shared close() */ @@ -147,7 +147,9 @@ int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, int falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags); int falloc_noinstall(struct thread *td, struct file **resultfp); -int finstall(struct thread *td, struct file *fp, int *resultfp, int flags, +void _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, + struct filecaps *fcaps); +int finstall(struct thread *td, struct file *fp, int *resultfd, int flags, struct filecaps *fcaps); int fdalloc(struct thread *td, int minfd, int *result); int fdallocn(struct thread *td, int minfd, int *fds, int n); @@ -163,7 +165,7 @@ 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 *rightsp, +int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); diff --git a/sys/sys/lockstat.h b/sys/sys/lockstat.h index ed9cffa..2a7853f 100644 --- a/sys/sys/lockstat.h +++ b/sys/sys/lockstat.h @@ -198,6 +198,9 @@ extern uint64_t lockstat_nsecs(void); (*lockstat_probe_func)(id, (uintptr_t)(lp), 0, 0, 0, 0); \ } while (0) +#define LOCKSTAT_WRITER 0 +#define LOCKSTAT_READER 1 + #else /* !KDTRACE_HOOKS */ #define LOCKSTAT_RECORD(probe, lp, arg1) diff --git a/sys/sys/param.h b/sys/sys/param.h index 098d8f8..a146da8 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 1100076 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100077 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index f4d46b2..e0e7fcb 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -105,7 +105,12 @@ __PMC_CPU(PPC_MPC85XX, 0x340, "Freescale PowerPC MPC85XX") \ __PMC_CPU(PPC_970, 0x380, "IBM PowerPC 970") \ __PMC_CPU(GENERIC, 0x400, "Generic") \ - __PMC_CPU(ARMV7, 0x500, "ARMv7") \ + __PMC_CPU(ARMV7_CORTEX_A5, 0x500, "ARMv7 Cortex A5") \ + __PMC_CPU(ARMV7_CORTEX_A7, 0x501, "ARMv7 Cortex A7") \ + __PMC_CPU(ARMV7_CORTEX_A8, 0x502, "ARMv7 Cortex A8") \ + __PMC_CPU(ARMV7_CORTEX_A9, 0x503, "ARMv7 Cortex A9") \ + __PMC_CPU(ARMV7_CORTEX_A15, 0x504, "ARMv7 Cortex A15") \ + __PMC_CPU(ARMV7_CORTEX_A17, 0x505, "ARMv7 Cortex A17") \ __PMC_CPU(ARMV8_CORTEX_A53, 0x600, "ARMv8 Cortex A53") \ __PMC_CPU(ARMV8_CORTEX_A57, 0x601, "ARMv8 Cortex A57") diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 018b595..e6c83b4 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -246,6 +246,7 @@ struct thread { int td_intr_nesting_level; /* (k) Interrupt recursion. */ int td_pinned; /* (k) Temporary cpu pin count. */ struct ucred *td_ucred; /* (k) Reference to credentials. */ + struct plimit *td_limit; /* (k) Resource limits. */ u_int td_estcpu; /* (t) estimated cpu utilization */ int td_slptick; /* (t) Time at sleep. */ int td_blktick; /* (t) Time spent blocked. */ @@ -308,6 +309,7 @@ struct thread { off_t tdu_off; } td_uretoff; /* (k) Syscall aux returns. */ #define td_retval td_uretoff.tdu_retval + u_int td_cowgen; /* (k) Generation of COW pointers. */ struct callout td_slpcallout; /* (h) Callout for sleep. */ struct trapframe *td_frame; /* (k) */ struct vm_object *td_kstack_obj;/* (a) Kstack object. */ @@ -498,7 +500,7 @@ struct proc { struct filedesc *p_fd; /* (b) Open files. */ struct filedesc_to_leader *p_fdtol; /* (b) Tracking node */ struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */ - struct plimit *p_limit; /* (c) Process limits. */ + struct plimit *p_limit; /* (c) Resource limits. */ struct callout p_limco; /* (c) Limit callout handle */ struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */ @@ -533,6 +535,7 @@ struct proc { pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */ struct vmspace *p_vmspace; /* (b) Address space. */ u_int p_swtick; /* (c) Tick when swapped in or out. */ + u_int p_cowgen; /* (c) Generation of COW pointers. */ struct itimerval p_realtimer; /* (c) Alarm timer. */ struct rusage p_ru; /* (a) Exit information. */ struct rusage_ext p_rux; /* (cu) Internal resource usage. */ @@ -833,6 +836,11 @@ extern pid_t pid_max; KASSERT((p)->p_lock == 0, ("process held")); \ } while (0) +#define PROC_UPDATE_COW(p) do { \ + PROC_LOCK_ASSERT((p), MA_OWNED); \ + (p)->p_cowgen++; \ +} while (0) + /* Check whether a thread is safe to be swapped out. */ #define thread_safetoswapout(td) ((td)->td_flags & TDF_CANSWAP) @@ -977,6 +985,10 @@ void cpu_thread_swapin(struct thread *); void cpu_thread_swapout(struct thread *); struct thread *thread_alloc(int pages); int thread_alloc_stack(struct thread *, int pages); +void thread_cow_get_proc(struct thread *newtd, struct proc *p); +void thread_cow_get(struct thread *newtd, struct thread *td); +void thread_cow_free(struct thread *td); +void thread_cow_update(struct thread *td); void thread_exit(void) __dead2; void thread_free(struct thread *td); void thread_link(struct thread *td, struct proc *p); diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h index a07fdf8..b4c707d 100644 --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -130,13 +130,16 @@ int kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, struct plimit *lim_alloc(void); void lim_copy(struct plimit *dst, struct plimit *src); -rlim_t lim_cur(struct proc *p, int which); +rlim_t lim_cur(struct thread *td, int which); +rlim_t lim_cur_proc(struct proc *p, int which); void lim_fork(struct proc *p1, struct proc *p2); void lim_free(struct plimit *limp); struct plimit *lim_hold(struct plimit *limp); -rlim_t lim_max(struct proc *p, int which); -void lim_rlimit(struct proc *p, int which, struct rlimit *rlp); +rlim_t lim_max(struct thread *td, int which); +rlim_t lim_max_proc(struct proc *p, int which); +void lim_rlimit(struct thread *td, int which, struct rlimit *rlp); +void lim_rlimit_proc(struct proc *p, int which, struct rlimit *rlp); void ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2, struct rusage_ext *rux2); void rucollect(struct rusage *ru, struct rusage *ru2); @@ -156,5 +159,7 @@ void ui_racct_foreach(void (*callback)(struct racct *racct, void *arg2, void *arg3), void *arg2, void *arg3); #endif +void lim_update_thread(struct thread *td); + #endif /* _KERNEL */ #endif /* !_SYS_RESOURCEVAR_H_ */ diff --git a/sys/sys/sbuf.h b/sys/sys/sbuf.h index 40de36e..580cbd2 100644 --- a/sys/sys/sbuf.h +++ b/sys/sys/sbuf.h @@ -58,6 +58,14 @@ struct sbuf { ssize_t s_sect_len; /* current length of section */ }; +#ifndef HD_COLUMN_MASK +#define HD_COLUMN_MASK 0xff +#define HD_DELIM_MASK 0xff00 +#define HD_OMIT_COUNT (1 << 16) +#define HD_OMIT_HEX (1 << 17) +#define HD_OMIT_CHARS (1 << 18) +#endif /* HD_COLUMN_MASK */ + __BEGIN_DECLS /* * API functions @@ -89,6 +97,8 @@ int sbuf_done(const struct sbuf *); void sbuf_delete(struct sbuf *); void sbuf_start_section(struct sbuf *, ssize_t *); ssize_t sbuf_end_section(struct sbuf *, ssize_t, size_t, int); +void sbuf_hexdump(struct sbuf *, const void *, int, const char *, + int); #ifdef _KERNEL struct uio; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index a30130f..36ef8af 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -692,7 +692,7 @@ int vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, struct ucred *active_cred, struct ucred *file_cred, size_t *aresid, struct thread *td); int vn_rlimit_fsize(const struct vnode *vn, const struct uio *uio, - const struct thread *td); + struct thread *td); int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, struct ucred *file_cred, struct thread *td); int vn_start_write(struct vnode *vp, struct mount **mpp, int flags); diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index c384064..2b9c334 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -2766,7 +2766,7 @@ 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, + if ((error = getvnode(td, cmd.handle, cap_rights_init(&rights, CAP_FSCK), &fp)) != 0) return (error); vp = fp->f_data; @@ -3080,7 +3080,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) (intmax_t)cmd.value); } #endif /* DEBUG */ - if ((error = getvnode(td->td_proc->p_fd, cmd.value, + if ((error = getvnode(td, cmd.value, cap_rights_init(&rights, CAP_FSCK), &vfp)) != 0) break; if (vfp->f_vnode->v_type != VCHR) { diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index ce43bcd..ffd8802 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1410,6 +1410,14 @@ ffs_statfs(mp, sbp) return (0); } +static bool +sync_doupdate(struct inode *ip) +{ + + return ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | + IN_UPDATE)) != 0); +} + /* * For a lazy sync, we only care about access times, quotas and the * superblock. Other filesystem changes are already converted to @@ -1443,15 +1451,15 @@ ffs_sync_lazy(mp) * Test also all the other timestamp flags too, to pick up * any other cases that could be missed. */ - if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | - IN_UPDATE)) == 0) { + if (!sync_doupdate(ip) && (vp->v_iflag & VI_OWEINACT) == 0) { VI_UNLOCK(vp); continue; } if ((error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td)) != 0) continue; - error = ffs_update(vp, 0); + if (sync_doupdate(ip)) + error = ffs_update(vp, 0); if (error != 0) allerror = error; vput(vp); diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 3005491..b3ad70e 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -224,16 +224,14 @@ swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred) mtx_unlock(&sw_dev_mtx); if (res) { - PROC_LOCK(curproc); UIDINFO_VMSIZE_LOCK(uip); if ((overcommit & SWAP_RESERVE_RLIMIT_ON) != 0 && - uip->ui_vmsize + incr > lim_cur(curproc, RLIMIT_SWAP) && + uip->ui_vmsize + incr > lim_cur(curthread, RLIMIT_SWAP) && priv_check(curthread, PRIV_VM_SWAP_NORLIMIT)) res = 0; else uip->ui_vmsize += incr; UIDINFO_VMSIZE_UNLOCK(uip); - PROC_UNLOCK(curproc); if (!res) { mtx_lock(&sw_dev_mtx); swap_reserved -= incr; @@ -1120,10 +1118,6 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) mreq = m[reqpage]; - KASSERT(mreq->object == object, - ("swap_pager_getpages: object mismatch %p/%p", - object, mreq->object)); - /* * Calculate range to retrieve. The pages have already been assigned * their swapblks. We require a *contiguous* range but we know it to diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 0c84d44..7391465 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -679,19 +679,12 @@ vnode_locked: /* * Found the page. Leave it busy while we play * with it. - */ - - /* - * Relookup in case pager changed page. Pager + * + * Pager could have changed the page. Pager * is responsible for disposition of old page * if moved. */ - fs.m = vm_page_lookup(fs.object, fs.pindex); - if (!fs.m) { - unlock_and_deallocate(&fs); - goto RetryFault; - } - + fs.m = marray[reqpage]; hardfault++; break; /* break to PAGE HAS BEEN FOUND */ } diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index c9ee890..1ff17c2 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -230,7 +230,7 @@ vsunlock(void *addr, size_t len) static vm_page_t vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) { - vm_page_t m, ma[1]; + vm_page_t m; vm_pindex_t pindex; int rv; @@ -238,11 +238,7 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) pindex = OFF_TO_IDX(offset); m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); if (m->valid != VM_PAGE_BITS_ALL) { - ma[0] = m; - rv = vm_pager_get_pages(object, ma, 1, 0); - m = vm_page_lookup(object, pindex); - if (m == NULL) - goto out; + rv = vm_pager_get_pages(object, &m, 1, 0); if (rv != VM_PAGER_OK) { vm_page_lock(m); vm_page_free(m); @@ -571,7 +567,7 @@ vm_thread_swapin(struct thread *td) { vm_object_t ksobj; vm_page_t ma[KSTACK_MAX_PAGES]; - int i, j, k, pages, rv; + int i, j, pages, rv; pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; @@ -593,9 +589,12 @@ vm_thread_swapin(struct thread *td) if (rv != VM_PAGER_OK) panic("vm_thread_swapin: cannot get kstack for proc: %d", td->td_proc->p_pid); + /* + * All pages in the array are in place, due to the + * pager is always the swap pager, which doesn't + * free or remove wired non-req pages from object. + */ vm_object_pip_wakeup(ksobj); - for (k = i; k < j; k++) - ma[k] = vm_page_lookup(ksobj, k); vm_page_xunbusy(ma[i]); } else if (vm_page_xbusied(ma[i])) vm_page_xunbusy(ma[i]); diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index d4527b3..fd16bf2 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -391,8 +391,7 @@ void kmem_unback(vm_object_t object, vm_offset_t addr, vm_size_t size) { vm_page_t m; - vm_offset_t offset; - int i; + vm_offset_t i, offset; KASSERT(object == kmem_object || object == kernel_object, ("kmem_unback: only supports kernel objects.")); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index bad9994..12ebf5d 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -3424,10 +3424,8 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, growsize = sgrowsiz; init_ssize = (max_ssize < growsize) ? max_ssize : growsize; vm_map_lock(map); - PROC_LOCK(curproc); - lmemlim = lim_cur(curproc, RLIMIT_MEMLOCK); - vmemlim = lim_cur(curproc, RLIMIT_VMEM); - PROC_UNLOCK(curproc); + lmemlim = lim_cur(curthread, RLIMIT_MEMLOCK); + vmemlim = lim_cur(curthread, RLIMIT_VMEM); if (!old_mlock && map->flags & MAP_WIREFUTURE) { if (ptoa(pmap_wired_count(map->pmap)) + init_ssize > lmemlim) { rv = KERN_NO_SPACE; @@ -3556,12 +3554,10 @@ vm_map_growstack(struct proc *p, vm_offset_t addr) int error; #endif + lmemlim = lim_cur(curthread, RLIMIT_MEMLOCK); + stacklim = lim_cur(curthread, RLIMIT_STACK); + vmemlim = lim_cur(curthread, RLIMIT_VMEM); Retry: - PROC_LOCK(p); - lmemlim = lim_cur(p, RLIMIT_MEMLOCK); - stacklim = lim_cur(p, RLIMIT_STACK); - vmemlim = lim_cur(p, RLIMIT_VMEM); - PROC_UNLOCK(p); vm_map_lock_read(map); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 489a987..d331a9b 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -316,9 +316,9 @@ sys_mmap(td, uap) if (addr == 0 || (addr >= round_page((vm_offset_t)vms->vm_taddr) && addr < round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)))) + lim_max_proc(td->td_proc, RLIMIT_DATA)))) addr = round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)); + lim_max_proc(td->td_proc, RLIMIT_DATA)); PROC_UNLOCK(td->td_proc); } if (size == 0) { @@ -1028,7 +1028,7 @@ vm_mlock(struct proc *proc, struct ucred *cred, const void *addr0, size_t len) map = &proc->p_vmspace->vm_map; PROC_LOCK(proc); nsize = ptoa(npages + pmap_wired_count(map->pmap)); - if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) { + if (nsize > lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); return (ENOMEM); } @@ -1088,7 +1088,7 @@ sys_mlockall(td, uap) */ if (!old_mlock && uap->how & MCL_CURRENT) { PROC_LOCK(td->td_proc); - if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { + if (map->size > lim_cur(td, RLIMIT_MEMLOCK)) { PROC_UNLOCK(td->td_proc); return (ENOMEM); } @@ -1481,7 +1481,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, if (map == &td->td_proc->p_vmspace->vm_map) { PROC_LOCK(td->td_proc); - if (map->size + size > lim_cur(td->td_proc, RLIMIT_VMEM)) { + if (map->size + size > lim_cur_proc(td->td_proc, RLIMIT_VMEM)) { PROC_UNLOCK(td->td_proc); return (ENOMEM); } @@ -1491,7 +1491,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, } if (!old_mlock && map->flags & MAP_WIREFUTURE) { if (ptoa(pmap_wired_count(map->pmap)) + size > - lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { + lim_cur_proc(td->td_proc, RLIMIT_MEMLOCK)) { racct_set_force(td->td_proc, RACCT_VMEM, map->size); PROC_UNLOCK(td->td_proc); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index e240b67..c7f3153 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -2046,7 +2046,7 @@ vm_object_page_cache(vm_object_t object, vm_pindex_t start, vm_pindex_t end) boolean_t vm_object_populate(vm_object_t object, vm_pindex_t start, vm_pindex_t end) { - vm_page_t m, ma[1]; + vm_page_t m; vm_pindex_t pindex; int rv; @@ -2054,11 +2054,7 @@ vm_object_populate(vm_object_t object, vm_pindex_t start, vm_pindex_t end) for (pindex = start; pindex < end; pindex++) { m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); if (m->valid != VM_PAGE_BITS_ALL) { - ma[0] = m; - rv = vm_pager_get_pages(object, ma, 1, 0); - m = vm_page_lookup(object, pindex); - if (m == NULL) - break; + rv = vm_pager_get_pages(object, &m, 1, 0); if (rv != VM_PAGER_OK) { vm_page_lock(m); vm_page_free(m); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 2f57579..bd77500 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1159,6 +1159,17 @@ vm_pageout_scan(struct vm_domain *vmd, int pass) queues_locked = FALSE; /* + * Invalid pages can be easily freed. They cannot be + * mapped, vm_page_free() asserts this. + */ + if (m->valid == 0 && m->hold_count == 0) { + vm_page_free(m); + PCPU_INC(cnt.v_dfree); + --page_shortage; + goto drop_page; + } + + /* * We bump the activation count if the page has been * referenced while in the inactive queue. This makes * it less likely that the page will be added back to the @@ -1192,15 +1203,10 @@ vm_pageout_scan(struct vm_domain *vmd, int pass) queues_locked = TRUE; vm_page_requeue_locked(m); } - VM_OBJECT_WUNLOCK(object); - vm_page_unlock(m); - goto relock_queues; + goto drop_page; } if (m->hold_count != 0) { - vm_page_unlock(m); - VM_OBJECT_WUNLOCK(object); - /* * Held pages are essentially stuck in the * queue. So, they ought to be discounted @@ -1209,7 +1215,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass) * loop over the active queue below. */ addl_page_shortage++; - goto relock_queues; + goto drop_page; } /* @@ -1224,20 +1230,13 @@ vm_pageout_scan(struct vm_domain *vmd, int pass) if (m->dirty == 0 && object->ref_count != 0) pmap_remove_all(m); - if (m->valid == 0) { + if (m->dirty == 0) { /* - * Invalid pages can be easily freed + * Clean pages can be freed. */ vm_page_free(m); PCPU_INC(cnt.v_dfree); --page_shortage; - } else if (m->dirty == 0) { - /* - * Clean pages can be placed onto the cache queue. - * This effectively frees them. - */ - vm_page_cache(m); - --page_shortage; } else if ((m->flags & PG_WINATCFLS) == 0 && pass < 2) { /* * Dirty pages need to be paged out, but flushing @@ -1305,6 +1304,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass) vm_page_lock_assert(m, MA_NOTOWNED); goto relock_queues; } +drop_page: vm_page_unlock(m); VM_OBJECT_WUNLOCK(object); relock_queues: @@ -1851,7 +1851,7 @@ again: /* * get a limit */ - lim_rlimit(p, RLIMIT_RSS, &rsslim); + lim_rlimit_proc(p, RLIMIT_RSS, &rsslim); limit = OFF_TO_IDX( qmin(rsslim.rlim_cur, rsslim.rlim_max)); diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index ed9b562..b4fe8d0 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -250,8 +250,78 @@ vm_pager_deallocate(object) (*pagertab[object->type]->pgo_dealloc) (object); } +static void +vm_pager_assert_in(vm_object_t object, vm_page_t *m, int count) +{ +#ifdef INVARIANTS + + VM_OBJECT_ASSERT_WLOCKED(object); + KASSERT(count > 0, ("%s: 0 count", __func__)); + /* + * All pages must be busied, not mapped, not fully valid, + * not dirty and belong to the proper object. + */ + for (int i = 0 ; i < count; i++) { + vm_page_assert_xbusied(m[i]); + KASSERT(!pmap_page_is_mapped(m[i]), + ("%s: page %p is mapped", __func__, m[i])); + KASSERT(m[i]->valid != VM_PAGE_BITS_ALL, + ("%s: request for a valid page %p", __func__, m[i])); + KASSERT(m[i]->dirty == 0, + ("%s: page %p is dirty", __func__, m[i])); + KASSERT(m[i]->object == object, + ("%s: wrong object %p/%p", __func__, object, m[i]->object)); + } +#endif +} + +/* + * Page in the pages for the object using its associated pager. + * The requested page must be fully valid on successful return. + */ +int +vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int reqpage) +{ + int r; + + vm_pager_assert_in(object, m, count); + + r = (*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage); + if (r != VM_PAGER_OK) + return (r); + + /* + * If pager has replaced the page, assert that it had + * updated the array. Also assert that page is still + * busied. + */ + KASSERT(m[reqpage] == vm_page_lookup(object, m[reqpage]->pindex), + ("%s: mismatch page %p pindex %ju", __func__, + m[reqpage], (uintmax_t )m[reqpage]->pindex)); + vm_page_assert_xbusied(m[reqpage]); + + /* + * Pager didn't fill up entire page. Zero out + * partially filled data. + */ + if (m[reqpage]->valid != VM_PAGE_BITS_ALL) + vm_page_zero_invalid(m[reqpage], TRUE); + + return (VM_PAGER_OK); +} + +int +vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count, + int reqpage, pgo_getpages_iodone_t iodone, void *arg) +{ + + vm_pager_assert_in(object, m, count); + + return ((*pagertab[object->type]->pgo_getpages_async)(object, m, + count, reqpage, iodone, arg)); +} + /* - * vm_pager_get_pages() - inline, see vm/vm_pager.h * vm_pager_put_pages() - inline, see vm/vm_pager.h * vm_pager_has_page() - inline, see vm/vm_pager.h */ diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h index 3accc69..6884729 100644 --- a/sys/vm/vm_pager.h +++ b/sys/vm/vm_pager.h @@ -106,49 +106,15 @@ vm_object_t vm_pager_allocate(objtype_t, void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t, struct ucred *); void vm_pager_bufferinit(void); void vm_pager_deallocate(vm_object_t); -static __inline int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int); -static inline int vm_pager_get_pages_async(vm_object_t, vm_page_t *, int, - int, pgo_getpages_iodone_t, void *); +int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int); +int vm_pager_get_pages_async(vm_object_t, vm_page_t *, int, int, + pgo_getpages_iodone_t, void *); static __inline boolean_t vm_pager_has_page(vm_object_t, vm_pindex_t, int *, int *); void vm_pager_init(void); vm_object_t vm_pager_object_lookup(struct pagerlst *, void *); void vm_pager_free_nonreq(vm_object_t object, vm_page_t ma[], int reqpage, int npages, boolean_t object_locked); -/* - * vm_page_get_pages: - * - * Retrieve pages from the VM system in order to map them into an object - * ( or into VM space somewhere ). If the pagein was successful, we - * must fully validate it. - */ -static __inline int -vm_pager_get_pages( - vm_object_t object, - vm_page_t *m, - int count, - int reqpage -) { - int r; - - VM_OBJECT_ASSERT_WLOCKED(object); - r = (*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage); - if (r == VM_PAGER_OK && m[reqpage]->valid != VM_PAGE_BITS_ALL) { - vm_page_zero_invalid(m[reqpage], TRUE); - } - return (r); -} - -static inline int -vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count, - int reqpage, pgo_getpages_iodone_t iodone, void *arg) -{ - - VM_OBJECT_ASSERT_WLOCKED(object); - return ((*pagertab[object->type]->pgo_getpages_async)(object, m, - count, reqpage, iodone, arg)); -} - static __inline void vm_pager_put_pages( vm_object_t object, diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c index cc77ff7..201c13b 100644 --- a/sys/vm/vm_unix.c +++ b/sys/vm/vm_unix.c @@ -83,11 +83,9 @@ sys_obreak(td, uap) int error = 0; boolean_t do_map_wirefuture; - PROC_LOCK(td->td_proc); - datalim = lim_cur(td->td_proc, RLIMIT_DATA); - lmemlim = lim_cur(td->td_proc, RLIMIT_MEMLOCK); - vmemlim = lim_cur(td->td_proc, RLIMIT_VMEM); - PROC_UNLOCK(td->td_proc); + datalim = lim_cur(td, RLIMIT_DATA); + lmemlim = lim_cur(td, RLIMIT_MEMLOCK); + vmemlim = lim_cur(td, RLIMIT_VMEM); do_map_wirefuture = FALSE; new = round_page((vm_offset_t)uap->nsize); diff --git a/sys/x86/acpica/acpi_wakeup.c b/sys/x86/acpica/acpi_wakeup.c index 0eb6823..bc1c55c 100644 --- a/sys/x86/acpica/acpi_wakeup.c +++ b/sys/x86/acpica/acpi_wakeup.c @@ -210,7 +210,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) if (acpi_resume_beep != 0) timer_spkr_acquire(); - AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc)); + AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc), 0); intr_suspend(); @@ -298,7 +298,7 @@ acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, #endif intr_resume(/*suspend_cancelled*/false); - AcpiSetFirmwareWakingVector(0); + AcpiSetFirmwareWakingVector(0, 0); } else { /* Wakeup MD procedures in interrupt enabled context */ if (sleep_result == 1 && mem_range_softc.mr_op != NULL && diff --git a/sys/xen/blkif.h b/sys/xen/blkif.h index 48b71ea..8a19d5d 100644 --- a/sys/xen/blkif.h +++ b/sys/xen/blkif.h @@ -46,7 +46,7 @@ struct blkif_x86_32_request { blkif_vdev_t handle; /* only for read/write requests */ uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK]; + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; }; struct blkif_x86_32_response { uint64_t id; /* copied from request */ @@ -64,7 +64,7 @@ struct blkif_x86_64_request { blkif_vdev_t handle; /* only for read/write requests */ uint64_t __attribute__((__aligned__(8))) id; blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK]; + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; }; struct blkif_x86_64_response { uint64_t __attribute__((__aligned__(8))) id; @@ -114,7 +114,7 @@ enum blkif_protocol { static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src) { - int i, n = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; dst->operation = src->operation; dst->nr_segments = src->nr_segments; dst->handle = src->handle; @@ -129,7 +129,7 @@ static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src) { - int i, n = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; dst->operation = src->operation; dst->nr_segments = src->nr_segments; dst->handle = src->handle; diff --git a/sys/xen/interface/io/blkif.h b/sys/xen/interface/io/blkif.h index 9155662..b725776 100644 --- a/sys/xen/interface/io/blkif.h +++ b/sys/xen/interface/io/blkif.h @@ -457,21 +457,9 @@ #define BLKIF_OP_DISCARD 5 /* - * Maximum scatter/gather segments associated with a request header block. - * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE. - * NB. This could be 12 if the ring indexes weren't stored in the same page. - */ -#define BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK 11 - -/* - * Maximum scatter/gather segments associated with a segment block. - */ -#define BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK 14 - -/* * Maximum scatter/gather segments per request (header + segment blocks). */ -#define BLKIF_MAX_SEGMENTS_PER_REQUEST 255 +#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 /* * NB. first_sect and last_sect in blkif_request_segment, as well as @@ -512,22 +500,11 @@ struct blkif_request { blkif_vdev_t handle; /* only for read/write requests */ uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - blkif_request_segment_t seg[BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK]; + blkif_request_segment_t seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; }; typedef struct blkif_request blkif_request_t; /* - * A segment block is a ring request structure that contains only - * segment data. - * - * sizeof(struct blkif_segment_block) <= sizeof(struct blkif_request) - */ -struct blkif_segment_block { - blkif_request_segment_t seg[BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK]; -}; -typedef struct blkif_segment_block blkif_segment_block_t; - -/* * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request) */ @@ -564,21 +541,6 @@ typedef struct blkif_response blkif_response_t; */ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); -/* - * Index to, and treat as a segment block, an entry in the ring. - */ -#define BLKRING_GET_SEG_BLOCK(_r, _idx) \ - (((blkif_segment_block_t *)RING_GET_REQUEST(_r, _idx))->seg) - -/* - * The number of ring request blocks required to handle an I/O - * request containing _segs segments. - */ -#define BLKIF_SEGS_TO_BLOCKS(_segs) \ - ((((_segs - BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK) \ - + (BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK - 1)) \ - / BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK) + /*header_block*/1) - #define VDISK_CDROM 0x1 #define VDISK_REMOVABLE 0x2 #define VDISK_READONLY 0x4 |