diff options
author | Renato Botelho <renato@netgate.com> | 2016-06-06 08:04:21 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-06-06 08:04:21 -0300 |
commit | 4fdb7654ef71cc3e4f0353cc46f28f652cd35605 (patch) | |
tree | 9ac039033dcfd7239eb7ae855bb794ff7d54bfad /sys/kern | |
parent | a361452ba60086e37d1776522ab3ea1f7e153e9d (diff) | |
parent | 4948c572e7d17a6c09d98026c5a15de8d7b71e09 (diff) | |
download | FreeBSD-src-4fdb7654ef71cc3e4f0353cc46f28f652cd35605.zip FreeBSD-src-4fdb7654ef71cc3e4f0353cc46f28f652cd35605.tar.gz |
Merge remote-tracking branch 'origin/master' into devel-11
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/bus_if.m | 29 | ||||
-rw-r--r-- | sys/kern/init_main.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_thread.c | 1 | ||||
-rw-r--r-- | sys/kern/sched_4bsd.c | 60 | ||||
-rw-r--r-- | sys/kern/sched_ule.c | 94 | ||||
-rw-r--r-- | sys/kern/subr_bus.c | 94 | ||||
-rw-r--r-- | sys/kern/subr_intr.c | 131 |
10 files changed, 296 insertions, 124 deletions
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m index 2b75438..d5a0c45 100644 --- a/sys/kern/bus_if.m +++ b/sys/kern/bus_if.m @@ -418,6 +418,35 @@ METHOD int release_resource { }; /** + * @brief Map an interrupt + * + * This method is used to get an interrupt mapping data according to provided + * hints. The hints could be modified afterwards, but only if mapping data was + * allocated. This method is intended to be called before BUS_ALLOC_RESOURCE(). + * + * @param _dev the parent device of @p _child + * @param _child the device which is requesting an allocation + * @param _rid a pointer to the resource identifier + * @param _start a pointer to the hint at the start of the resource + * range - pass @c 0 for any start address + * @param _end a pointer to the hint at the end of the resource + * range - pass @c ~0 for any end address + * @param _count a pointer to the hint at the size of resource + * range required - pass @c 1 for any size + * @param _imd a pointer to the interrupt mapping data which was + * allocated + */ +METHOD int map_intr { + device_t _dev; + device_t _child; + int *_rid; + rman_res_t *_start; + rman_res_t *_end; + rman_res_t *_count; + struct intr_map_data **_imd; +} DEFAULT bus_generic_map_intr; + +/** * @brief Install an interrupt handler * * This method is used to associate an interrupt handler function with diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 6e54f36..9b1d2ac 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -99,7 +99,7 @@ void mi_startup(void); /* Should be elsewhere */ static struct session session0; static struct pgrp pgrp0; struct proc proc0; -struct thread thread0 __aligned(16); +struct thread0_storage thread0_st __aligned(16); struct vmspace vmspace0; struct proc *initproc; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index fbc96a4..e004097 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1011,7 +1011,7 @@ fork_exit(void (*callout)(void *, struct trapframe *), void *arg, KASSERT(p->p_state == PRS_NORMAL, ("executing process is still new")); CTR4(KTR_PROC, "fork_exit: new thread %p (td_sched %p, pid %d, %s)", - td, td->td_sched, p->p_pid, td->td_name); + td, td_get_sched(td), p->p_pid, td->td_name); sched_fork_exit(td); /* diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 9dabf7c..2f1f620 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -168,7 +168,7 @@ CTASSERT(sizeof(struct kinfo_proc32) == KINFO_PROC32_SIZE); * Initialize global process hashing structures. */ void -procinit() +procinit(void) { sx_init(&allproc_lock, "allproc"); @@ -237,7 +237,6 @@ proc_init(void *mem, int size, int flags) p = (struct proc *)mem; SDT_PROBE3(proc, , init, entry, p, size, flags); - p->p_sched = (struct p_sched *)&p[1]; mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK | MTX_NEW); mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_NEW); mtx_init(&p->p_statmtx, "pstatl", NULL, MTX_SPIN | MTX_NEW); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 55df6a0..358cce3 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -441,7 +441,7 @@ mi_switch(int flags, struct thread *newtd) PCPU_INC(cnt.v_swtch); PCPU_SET(switchticks, ticks); CTR4(KTR_PROC, "mi_switch: old thread %ld (td_sched %p, pid %ld, %s)", - td->td_tid, td->td_sched, td->td_proc->p_pid, td->td_name); + td->td_tid, td_get_sched(td), td->td_proc->p_pid, td->td_name); #if (KTR_COMPILE & KTR_SCHED) != 0 if (TD_IS_IDLETHREAD(td)) KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "idle", @@ -457,7 +457,7 @@ mi_switch(int flags, struct thread *newtd) "prio:%d", td->td_priority); CTR4(KTR_PROC, "mi_switch: new thread %ld (td_sched %p, pid %ld, %s)", - td->td_tid, td->td_sched, td->td_proc->p_pid, td->td_name); + td->td_tid, td_get_sched(td), td->td_proc->p_pid, td->td_name); /* * If the last thread was exiting, finish cleaning it up. diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 21f3587..9af377e 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -211,7 +211,6 @@ thread_init(void *mem, int size, int flags) td->td_turnstile = turnstile_alloc(); td->td_rlqe = NULL; EVENTHANDLER_INVOKE(thread_init, td); - td->td_sched = (struct td_sched *)&td[1]; umtx_thread_init(td); td->td_kstack = 0; td->td_sel = NULL; diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index 25afe98..7de56b6 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -117,7 +117,10 @@ struct td_sched { #define THREAD_CAN_SCHED(td, cpu) \ CPU_ISSET((cpu), &(td)->td_cpuset->cs_mask) -static struct td_sched td_sched0; +_Static_assert(sizeof(struct thread) + sizeof(struct td_sched) <= + sizeof(struct thread0_storage), + "increase struct thread0_storage.t0st_sched size"); + static struct mtx sched_lock; static int realstathz = 127; /* stathz is sometimes 0 and run off of hz. */ @@ -491,8 +494,8 @@ schedcpu(void) } FOREACH_THREAD_IN_PROC(p, td) { awake = 0; + ts = td_get_sched(td); thread_lock(td); - ts = td->td_sched; /* * Increment sleep time (if sleeping). We * ignore overflow, as above. @@ -596,7 +599,7 @@ updatepri(struct thread *td) fixpt_t loadfac; unsigned int newcpu; - ts = td->td_sched; + ts = td_get_sched(td); loadfac = loadfactor(averunnable.ldavg[0]); if (ts->ts_slptime > 5 * loadfac) ts->ts_estcpu = 0; @@ -621,7 +624,8 @@ resetpriority(struct thread *td) if (td->td_pri_class != PRI_TIMESHARE) return; - newpriority = PUSER + td->td_sched->ts_estcpu / INVERSE_ESTCPU_WEIGHT + + newpriority = PUSER + + td_get_sched(td)->ts_estcpu / INVERSE_ESTCPU_WEIGHT + NICE_WEIGHT * (td->td_proc->p_nice - PRIO_MIN); newpriority = min(max(newpriority, PRI_MIN_TIMESHARE), PRI_MAX_TIMESHARE); @@ -682,13 +686,12 @@ sched_initticks(void *dummy) void schedinit(void) { + /* - * Set up the scheduler specific parts of proc0. + * Set up the scheduler specific parts of thread0. */ - proc0.p_sched = NULL; /* XXX */ - thread0.td_sched = &td_sched0; thread0.td_lock = &sched_lock; - td_sched0.ts_slice = sched_slice; + td_get_sched(&thread0)->ts_slice = sched_slice; mtx_init(&sched_lock, "sched lock", NULL, MTX_SPIN | MTX_RECURSE); } @@ -731,7 +734,7 @@ sched_clock(struct thread *td) struct td_sched *ts; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); ts->ts_cpticks++; ts->ts_estcpu = ESTCPULIM(ts->ts_estcpu + 1); @@ -775,8 +778,8 @@ sched_exit_thread(struct thread *td, struct thread *child) KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "exit", "prio:%d", child->td_priority); thread_lock(td); - td->td_sched->ts_estcpu = ESTCPULIM(td->td_sched->ts_estcpu + - child->td_sched->ts_estcpu); + td_get_sched(td)->ts_estcpu = ESTCPULIM(td_get_sched(td)->ts_estcpu + + td_get_sched(child)->ts_estcpu); thread_unlock(td); thread_lock(child); if ((child->td_flags & TDF_NOLOAD) == 0) @@ -793,17 +796,18 @@ sched_fork(struct thread *td, struct thread *childtd) void sched_fork_thread(struct thread *td, struct thread *childtd) { - struct td_sched *ts; + struct td_sched *ts, *tsc; childtd->td_oncpu = NOCPU; childtd->td_lastcpu = NOCPU; childtd->td_lock = &sched_lock; childtd->td_cpuset = cpuset_ref(td->td_cpuset); childtd->td_priority = childtd->td_base_pri; - ts = childtd->td_sched; + ts = td_get_sched(childtd); bzero(ts, sizeof(*ts)); - ts->ts_estcpu = td->td_sched->ts_estcpu; - ts->ts_flags |= (td->td_sched->ts_flags & TSF_AFFINITY); + tsc = td_get_sched(td); + ts->ts_estcpu = tsc->ts_estcpu; + ts->ts_flags |= (tsc->ts_flags & TSF_AFFINITY); ts->ts_slice = 1; } @@ -952,7 +956,7 @@ sched_sleep(struct thread *td, int pri) THREAD_LOCK_ASSERT(td, MA_OWNED); td->td_slptick = ticks; - td->td_sched->ts_slptime = 0; + td_get_sched(td)->ts_slptime = 0; if (pri != 0 && PRI_BASE(td->td_pri_class) == PRI_TIMESHARE) sched_prio(td, pri); if (TD_IS_SUSPENDED(td) || pri >= PSOCK) @@ -968,7 +972,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) int preempted; tmtx = NULL; - ts = td->td_sched; + ts = td_get_sched(td); p = td->td_proc; THREAD_LOCK_ASSERT(td, MA_OWNED); @@ -1095,7 +1099,7 @@ sched_wakeup(struct thread *td) struct td_sched *ts; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); td->td_flags &= ~TDF_CANSWAP; if (ts->ts_slptime > 1) { updatepri(td); @@ -1266,7 +1270,7 @@ sched_add(struct thread *td, int flags) int forwarded = 0; int single_cpu = 0; - ts = td->td_sched; + ts = td_get_sched(td); THREAD_LOCK_ASSERT(td, MA_OWNED); KASSERT((td->td_inhibitors == 0), ("sched_add: trying to run inhibited thread")); @@ -1361,7 +1365,7 @@ sched_add(struct thread *td, int flags) { struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); THREAD_LOCK_ASSERT(td, MA_OWNED); KASSERT((td->td_inhibitors == 0), ("sched_add: trying to run inhibited thread")); @@ -1414,7 +1418,7 @@ sched_rem(struct thread *td) { struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); KASSERT(td->td_flags & TDF_INMEM, ("sched_rem: thread swapped out")); KASSERT(TD_ON_RUNQ(td), @@ -1527,7 +1531,7 @@ sched_bind(struct thread *td, int cpu) THREAD_LOCK_ASSERT(td, MA_OWNED|MA_NOTRECURSED); KASSERT(td == curthread, ("sched_bind: can only bind curthread")); - ts = td->td_sched; + ts = td_get_sched(td); td->td_flags |= TDF_BOUND; #ifdef SMP @@ -1586,7 +1590,7 @@ sched_pctcpu(struct thread *td) struct td_sched *ts; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); return (ts->ts_pctcpu); } @@ -1603,7 +1607,7 @@ sched_pctcpu_delta(struct thread *td) int realstathz; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); delta = 0; realstathz = stathz ? stathz : hz; if (ts->ts_cpticks != 0) { @@ -1628,7 +1632,7 @@ u_int sched_estcpu(struct thread *td) { - return (td->td_sched->ts_estcpu); + return (td_get_sched(td)->ts_estcpu); } /* @@ -1707,7 +1711,7 @@ sched_tdname(struct thread *td) #ifdef KTR struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); if (ts->ts_name[0] == '\0') snprintf(ts->ts_name, sizeof(ts->ts_name), "%s tid %d", td->td_name, td->td_tid); @@ -1723,7 +1727,7 @@ sched_clear_tdname(struct thread *td) { struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); ts->ts_name[0] = '\0'; } #endif @@ -1741,7 +1745,7 @@ sched_affinity(struct thread *td) * Set the TSF_AFFINITY flag if there is at least one CPU this * thread can't run on. */ - ts = td->td_sched; + ts = td_get_sched(td); ts->ts_flags &= ~TSF_AFFINITY; CPU_FOREACH(cpu) { if (!THREAD_CAN_SCHED(td, cpu)) { diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index 37aa6bc..8af976b 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -106,12 +106,14 @@ struct td_sched { #define TSF_BOUND 0x0001 /* Thread can not migrate. */ #define TSF_XFERABLE 0x0002 /* Thread was added as transferable. */ -static struct td_sched td_sched0; - #define THREAD_CAN_MIGRATE(td) ((td)->td_pinned == 0) #define THREAD_CAN_SCHED(td, cpu) \ CPU_ISSET((cpu), &(td)->td_cpuset->cs_mask) +_Static_assert(sizeof(struct thread) + sizeof(struct td_sched) <= + sizeof(struct thread0_storage), + "increase struct thread0_storage.t0st_sched size"); + /* * Priority ranges used for interactive and non-interactive timeshare * threads. The timeshare priorities are split up into four ranges. @@ -460,7 +462,7 @@ tdq_runq_add(struct tdq *tdq, struct thread *td, int flags) THREAD_LOCK_ASSERT(td, MA_OWNED); pri = td->td_priority; - ts = td->td_sched; + ts = td_get_sched(td); TD_SET_RUNQ(td); if (THREAD_CAN_MIGRATE(td)) { tdq->tdq_transferable++; @@ -506,7 +508,7 @@ tdq_runq_rem(struct tdq *tdq, struct thread *td) { struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); TDQ_LOCK_ASSERT(tdq, MA_OWNED); KASSERT(ts->ts_runq != NULL, ("tdq_runq_remove: thread %p null ts_runq", td)); @@ -962,7 +964,7 @@ tdq_move(struct tdq *from, struct tdq *to) td = tdq_steal(tdq, cpu); if (td == NULL) return (0); - ts = td->td_sched; + ts = td_get_sched(td); /* * Although the run queue is locked the thread may be blocked. Lock * it to clear this and acquire the run-queue lock. @@ -1046,7 +1048,7 @@ tdq_notify(struct tdq *tdq, struct thread *td) if (tdq->tdq_ipipending) return; - cpu = td->td_sched->ts_cpu; + cpu = td_get_sched(td)->ts_cpu; pri = td->td_priority; ctd = pcpu_find(cpu)->pc_curthread; if (!sched_shouldpreempt(pri, ctd->td_priority, 1)) @@ -1174,7 +1176,7 @@ sched_setcpu(struct thread *td, int cpu, int flags) THREAD_LOCK_ASSERT(td, MA_OWNED); tdq = TDQ_CPU(cpu); - td->td_sched->ts_cpu = cpu; + td_get_sched(td)->ts_cpu = cpu; /* * If the lock matches just return the queue. */ @@ -1221,7 +1223,7 @@ sched_pickcpu(struct thread *td, int flags) int cpu, pri, self; self = PCPU_GET(cpuid); - ts = td->td_sched; + ts = td_get_sched(td); if (smp_started == 0) return (self); /* @@ -1472,7 +1474,7 @@ sched_interact_score(struct thread *td) struct td_sched *ts; int div; - ts = td->td_sched; + ts = td_get_sched(td); /* * The score is only needed if this is likely to be an interactive * task. Don't go through the expense of computing it if there's @@ -1537,16 +1539,16 @@ sched_priority(struct thread *td) pri, score)); } else { pri = SCHED_PRI_MIN; - if (td->td_sched->ts_ticks) - pri += min(SCHED_PRI_TICKS(td->td_sched), + if (td_get_sched(td)->ts_ticks) + pri += min(SCHED_PRI_TICKS(td_get_sched(td)), SCHED_PRI_RANGE - 1); pri += SCHED_PRI_NICE(td->td_proc->p_nice); KASSERT(pri >= PRI_MIN_BATCH && pri <= PRI_MAX_BATCH, ("sched_priority: invalid priority %d: nice %d, " "ticks %d ftick %d ltick %d tick pri %d", - pri, td->td_proc->p_nice, td->td_sched->ts_ticks, - td->td_sched->ts_ftick, td->td_sched->ts_ltick, - SCHED_PRI_TICKS(td->td_sched))); + pri, td->td_proc->p_nice, td_get_sched(td)->ts_ticks, + td_get_sched(td)->ts_ftick, td_get_sched(td)->ts_ltick, + SCHED_PRI_TICKS(td_get_sched(td)))); } sched_user_prio(td, pri); @@ -1564,7 +1566,7 @@ sched_interact_update(struct thread *td) struct td_sched *ts; u_int sum; - ts = td->td_sched; + ts = td_get_sched(td); sum = ts->ts_runtime + ts->ts_slptime; if (sum < SCHED_SLP_RUN_MAX) return; @@ -1606,14 +1608,16 @@ sched_interact_update(struct thread *td) static void sched_interact_fork(struct thread *td) { + struct td_sched *ts; int ratio; int sum; - sum = td->td_sched->ts_runtime + td->td_sched->ts_slptime; + ts = td_get_sched(td); + sum = ts->ts_runtime + ts->ts_slptime; if (sum > SCHED_SLP_RUN_FORK) { ratio = sum / SCHED_SLP_RUN_FORK; - td->td_sched->ts_runtime /= ratio; - td->td_sched->ts_slptime /= ratio; + ts->ts_runtime /= ratio; + ts->ts_slptime /= ratio; } } @@ -1623,15 +1627,15 @@ sched_interact_fork(struct thread *td) void schedinit(void) { + struct td_sched *ts0; /* - * Set up the scheduler specific parts of proc0. + * Set up the scheduler specific parts of thread0. */ - proc0.p_sched = NULL; /* XXX */ - thread0.td_sched = &td_sched0; - td_sched0.ts_ltick = ticks; - td_sched0.ts_ftick = ticks; - td_sched0.ts_slice = 0; + ts0 = td_get_sched(&thread0); + ts0->ts_ltick = ticks; + ts0->ts_ftick = ticks; + ts0->ts_slice = 0; } /* @@ -1694,7 +1698,7 @@ sched_thread_priority(struct thread *td, u_char prio) SDT_PROBE4(sched, , , lend__pri, td, td->td_proc, prio, curthread); } - ts = td->td_sched; + ts = td_get_sched(td); THREAD_LOCK_ASSERT(td, MA_OWNED); if (td->td_priority == prio) return; @@ -1829,7 +1833,7 @@ sched_switch_migrate(struct tdq *tdq, struct thread *td, int flags) { struct tdq *tdn; - tdn = TDQ_CPU(td->td_sched->ts_cpu); + tdn = TDQ_CPU(td_get_sched(td)->ts_cpu); #ifdef SMP tdq_load_rem(tdq, td); /* @@ -1888,7 +1892,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) cpuid = PCPU_GET(cpuid); tdq = TDQ_CPU(cpuid); - ts = td->td_sched; + ts = td_get_sched(td); mtx = td->td_lock; sched_pctcpu_update(ts, 1); ts->ts_rltick = ticks; @@ -1948,7 +1952,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) SDT_PROBE2(sched, , , off__cpu, newtd, newtd->td_proc); lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object); TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd; - sched_pctcpu_update(newtd->td_sched, 0); + sched_pctcpu_update(td_get_sched(newtd), 0); #ifdef KDTRACE_HOOKS /* @@ -2038,7 +2042,7 @@ sched_wakeup(struct thread *td) int slptick; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); td->td_flags &= ~TDF_CANSWAP; /* * If we slept for more than a tick update our interactivity and @@ -2066,14 +2070,14 @@ void sched_fork(struct thread *td, struct thread *child) { THREAD_LOCK_ASSERT(td, MA_OWNED); - sched_pctcpu_update(td->td_sched, 1); + sched_pctcpu_update(td_get_sched(td), 1); sched_fork_thread(td, child); /* * Penalize the parent and child for forking. */ sched_interact_fork(child); sched_priority(child); - td->td_sched->ts_runtime += tickincr; + td_get_sched(td)->ts_runtime += tickincr; sched_interact_update(td); sched_priority(td); } @@ -2093,8 +2097,8 @@ sched_fork_thread(struct thread *td, struct thread *child) /* * Initialize child. */ - ts = td->td_sched; - ts2 = child->td_sched; + ts = td_get_sched(td); + ts2 = td_get_sched(child); child->td_oncpu = NOCPU; child->td_lastcpu = NOCPU; child->td_lock = TDQ_LOCKPTR(tdq); @@ -2169,7 +2173,7 @@ sched_exit_thread(struct thread *td, struct thread *child) * launch expensive things to mark their children as expensive. */ thread_lock(td); - td->td_sched->ts_runtime += child->td_sched->ts_runtime; + td_get_sched(td)->ts_runtime += td_get_sched(child)->ts_runtime; sched_interact_update(td); sched_priority(td); thread_unlock(td); @@ -2264,7 +2268,7 @@ sched_clock(struct thread *td) if (TAILQ_EMPTY(&tdq->tdq_timeshare.rq_queues[tdq->tdq_ridx])) tdq->tdq_ridx = tdq->tdq_idx; } - ts = td->td_sched; + ts = td_get_sched(td); sched_pctcpu_update(ts, 1); if (td->td_pri_class & PRI_FIFO_BIT) return; @@ -2273,7 +2277,7 @@ sched_clock(struct thread *td) * We used a tick; charge it to the thread so * that we can compute our interactivity. */ - td->td_sched->ts_runtime += tickincr; + td_get_sched(td)->ts_runtime += tickincr; sched_interact_update(td); sched_priority(td); } @@ -2455,7 +2459,7 @@ sched_rem(struct thread *td) KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "runq rem", "prio:%d", td->td_priority); SDT_PROBE3(sched, , , dequeue, td, td->td_proc, NULL); - tdq = TDQ_CPU(td->td_sched->ts_cpu); + tdq = TDQ_CPU(td_get_sched(td)->ts_cpu); TDQ_LOCK_ASSERT(tdq, MA_OWNED); MPASS(td->td_lock == TDQ_LOCKPTR(tdq)); KASSERT(TD_ON_RUNQ(td), @@ -2477,9 +2481,7 @@ sched_pctcpu(struct thread *td) struct td_sched *ts; pctcpu = 0; - ts = td->td_sched; - if (ts == NULL) - return (0); + ts = td_get_sched(td); THREAD_LOCK_ASSERT(td, MA_OWNED); sched_pctcpu_update(ts, TD_IS_RUNNING(td)); @@ -2505,7 +2507,7 @@ sched_affinity(struct thread *td) struct td_sched *ts; THREAD_LOCK_ASSERT(td, MA_OWNED); - ts = td->td_sched; + ts = td_get_sched(td); if (THREAD_CAN_SCHED(td, ts->ts_cpu)) return; if (TD_ON_RUNQ(td)) { @@ -2536,7 +2538,7 @@ sched_bind(struct thread *td, int cpu) THREAD_LOCK_ASSERT(td, MA_OWNED|MA_NOTRECURSED); KASSERT(td == curthread, ("sched_bind: can only bind curthread")); - ts = td->td_sched; + ts = td_get_sched(td); if (ts->ts_flags & TSF_BOUND) sched_unbind(td); KASSERT(THREAD_CAN_MIGRATE(td), ("%p must be migratable", td)); @@ -2559,7 +2561,7 @@ sched_unbind(struct thread *td) THREAD_LOCK_ASSERT(td, MA_OWNED); KASSERT(td == curthread, ("sched_unbind: can only bind curthread")); - ts = td->td_sched; + ts = td_get_sched(td); if ((ts->ts_flags & TSF_BOUND) == 0) return; ts->ts_flags &= ~TSF_BOUND; @@ -2570,7 +2572,7 @@ int sched_is_bound(struct thread *td) { THREAD_LOCK_ASSERT(td, MA_OWNED); - return (td->td_sched->ts_flags & TSF_BOUND); + return (td_get_sched(td)->ts_flags & TSF_BOUND); } /* @@ -2761,7 +2763,7 @@ sched_tdname(struct thread *td) #ifdef KTR struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); if (ts->ts_name[0] == '\0') snprintf(ts->ts_name, sizeof(ts->ts_name), "%s tid %d", td->td_name, td->td_tid); @@ -2777,7 +2779,7 @@ sched_clear_tdname(struct thread *td) { struct td_sched *ts; - ts = td->td_sched; + ts = td_get_sched(td); ts->ts_name[0] = '\0'; } #endif diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index f491643..af3ca57 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -3951,6 +3951,23 @@ bus_generic_new_pass(device_t dev) } /** + * @brief Helper function for implementing BUS_MAP_INTR(). + * + * This simple implementation of BUS_MAP_INTR() simply calls the + * BUS_MAP_INTR() method of the parent of @p dev. + */ +int +bus_generic_map_intr(device_t dev, device_t child, int *rid, rman_res_t *start, + rman_res_t *end, rman_res_t *count, struct intr_map_data **imd) +{ + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_MAP_INTR(dev->parent, child, rid, start, end, count, + imd)); + return (EINVAL); +} + +/** * @brief Helper function for implementing BUS_SETUP_INTR(). * * This simple implementation of BUS_SETUP_INTR() simply calls the @@ -4405,6 +4422,41 @@ bus_release_resources(device_t dev, const struct resource_spec *rs, } } +#ifdef INTRNG +/** + * @internal + * + * This can be converted to bus method later. (XXX) + */ +static struct intr_map_data * +bus_extend_resource(device_t dev, int type, int *rid, rman_res_t *start, + rman_res_t *end, rman_res_t *count) +{ + struct intr_map_data *imd; + struct resource_list *rl; + int rv; + + if (dev->parent == NULL) + return (NULL); + if (type != SYS_RES_IRQ) + return (NULL); + + if (!RMAN_IS_DEFAULT_RANGE(*start, *end)) + return (NULL); + rl = BUS_GET_RESOURCE_LIST(dev->parent, dev); + if (rl != NULL) { + if (resource_list_find(rl, type, *rid) != NULL) + return (NULL); + } + rv = BUS_MAP_INTR(dev->parent, dev, rid, start, end, count, &imd); + if (rv != 0) + return (NULL); + if (rl != NULL) + resource_list_add(rl, type, *rid, *start, *end, *count); + return (imd); +} +#endif + /** * @brief Wrapper function for BUS_ALLOC_RESOURCE(). * @@ -4412,13 +4464,31 @@ bus_release_resources(device_t dev, const struct resource_spec *rs, * parent of @p dev. */ struct resource * -bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, rman_res_t end, - rman_res_t count, u_int flags) +bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, + rman_res_t end, rman_res_t count, u_int flags) { + struct resource *res; +#ifdef INTRNG + struct intr_map_data *imd; +#endif + if (dev->parent == NULL) return (NULL); - return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, - count, flags)); + +#ifdef INTRNG + imd = bus_extend_resource(dev, type, rid, &start, &end, &count); +#endif + res = BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, + count, flags); +#ifdef INTRNG + if (imd != NULL) { + if (res != NULL && rman_get_virtual(res) == NULL) + rman_set_virtual(res, imd); + else + imd->destruct(imd); + } +#endif + return (res); } /** @@ -4503,9 +4573,23 @@ bus_unmap_resource(device_t dev, int type, struct resource *r, int bus_release_resource(device_t dev, int type, int rid, struct resource *r) { + int rv; +#ifdef INTRNG + struct intr_map_data *imd; +#endif + if (dev->parent == NULL) return (EINVAL); - return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r)); + +#ifdef INTRNG + imd = (type == SYS_RES_IRQ) ? rman_get_virtual(r) : NULL; +#endif + rv = BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r); +#ifdef INTRNG + if (imd != NULL) + imd->destruct(imd); +#endif + return (rv); } /** diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 7fcf7d7..5d18ea2 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -64,12 +64,6 @@ __FBSDID("$FreeBSD$"); #include <machine/smp.h> #include <machine/stdarg.h> -#ifdef FDT -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif - #ifdef DDB #include <ddb/ddb.h> #endif @@ -98,6 +92,15 @@ static intr_irq_filter_t *irq_root_filter; static void *irq_root_arg; static u_int irq_root_ipicount; +struct intr_pic_child { + SLIST_ENTRY(intr_pic_child) pc_next; + struct intr_pic *pc_pic; + intr_child_irq_filter_t *pc_filter; + void *pc_filter_arg; + uintptr_t pc_start; + uintptr_t pc_length; +}; + /* Interrupt controller definition. */ struct intr_pic { SLIST_ENTRY(intr_pic) pic_next; @@ -106,6 +109,8 @@ struct intr_pic { #define FLAG_PIC (1 << 0) #define FLAG_MSI (1 << 1) u_int pic_flags; + struct mtx pic_child_lock; + SLIST_HEAD(, intr_pic_child) pic_children; }; static struct mtx pic_list_lock; @@ -323,6 +328,29 @@ intr_irq_handler(struct trapframe *tf) #endif } +int +intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq) +{ + struct intr_pic_child *child; + bool found; + + found = false; + mtx_lock_spin(&parent->pic_child_lock); + SLIST_FOREACH(child, &parent->pic_children, pc_next) { + if (child->pc_start <= irq && + irq < (child->pc_start + child->pc_length)) { + found = true; + break; + } + } + mtx_unlock_spin(&parent->pic_child_lock); + + if (found) + return (child->pc_filter(child->pc_filter_arg, irq)); + + return (FILTER_STRAY); +} + /* * interrupt controller dispatch function for interrupts. It should * be called straight from the interrupt controller, when associated interrupt @@ -526,7 +554,6 @@ intr_ddata_alloc(u_int extsize) mtx_unlock(&isrc_table_lock); ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); - ddata->idd_data->size = extsize; return (ddata); } @@ -592,33 +619,6 @@ intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, return (ddata->idd_irq); } #endif -#ifdef FDT -/* - * Map interrupt source according to FDT data into framework. If such mapping - * does not exist, create it. Return unique interrupt number (resource handle) - * associated with mapped interrupt source. - */ -u_int -intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) -{ - size_t cellsize; - struct intr_dev_data *ddata; - struct intr_map_data_fdt *daf; - - cellsize = ncells * sizeof(*cells); - ddata = intr_ddata_alloc(sizeof(struct intr_map_data_fdt) + cellsize); - if (ddata == NULL) - return (INTR_IRQ_INVALID); /* no space left */ - - ddata->idd_xref = (intptr_t)node; - ddata->idd_data->type = INTR_MAP_DATA_FDT; - - daf = (struct intr_map_data_fdt *)ddata->idd_data; - daf->ncells = ncells; - memcpy(daf->cells, cells, cellsize); - return (ddata->idd_irq); -} -#endif /* * Store GPIO interrupt decription in framework and return unique interrupt @@ -892,6 +892,7 @@ pic_create(device_t dev, intptr_t xref) } pic->pic_xref = xref; pic->pic_dev = dev; + mtx_init(&pic->pic_child_lock, "pic child lock", NULL, MTX_SPIN); SLIST_INSERT_HEAD(&pic_list, pic, pic_next); mtx_unlock(&pic_list_lock); @@ -1001,6 +1002,44 @@ intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, return (0); } +/* + * Add a handler to manage a sub range of a parents interrupts. + */ +struct intr_pic * +intr_pic_add_handler(device_t parent, struct intr_pic *pic, + intr_child_irq_filter_t *filter, void *arg, uintptr_t start, + uintptr_t length) +{ + struct intr_pic *parent_pic; + struct intr_pic_child *newchild; +#ifdef INVARIANTS + struct intr_pic_child *child; +#endif + + parent_pic = pic_lookup(parent, 0); + if (parent_pic == NULL) + return (NULL); + + newchild = malloc(sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO); + newchild->pc_pic = pic; + newchild->pc_filter = filter; + newchild->pc_filter_arg = arg; + newchild->pc_start = start; + newchild->pc_length = length; + + mtx_lock_spin(&parent_pic->pic_child_lock); +#ifdef INVARIANTS + SLIST_FOREACH(child, &parent_pic->pic_children, pc_next) { + KASSERT(child->pc_pic != pic, ("%s: Adding a child PIC twice", + __func__)); + } +#endif + SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next); + mtx_unlock_spin(&parent_pic->pic_child_lock); + + return (pic); +} + int intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, u_int *irqp) @@ -1035,7 +1074,11 @@ intr_alloc_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1051,7 +1094,11 @@ intr_release_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1070,7 +1117,11 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1130,7 +1181,11 @@ intr_teardown_irq(device_t dev, struct resource *res, void *cookie) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); |