we did not interpret the $rootdir and $rootspec environment
variables right. $rootdir is what gets bound to / (usually /root)
and $rootspec is the mountspec of /root.
i'v been seeing the error condition described above in the
Slowbulkin comment. so i'm enabling the work arround which
seems to fix the lockup.
in the split transaction case where we want to start the
transaction at frame start, acquire the ctlr lock *before*
checking if we are in the right frame number. so the start
will happen atomically. checking the software ctlr->sofchan
instead of checking the interrupt mask register seems to
be quicker.
setting the haint mask bit for the chan under ctlr lock
in chanio() instead of chanwait() avoids needing to acquire
the ctlr lock twice.
mask wakechan bits with busychan bitmap in interrupt handlers
so we will not try to wake up released chans by accident.
sleep() and tsleep() might get interrupted so we have to
release the split qlock in the split transaction case and
in all cases, make sure to halt the channel before release.
add some common debug functions to dump channel and controller
registers.
we have to ensure that all stores saving the process state
have completed before setting up->mach = nil in the scheduler.
otherwise, another cpu could observe up->mach == nil while
the stores such as the processes p->sched label have not finnished.
attached is a patch to fix receive in the 8169 chip on my thinkpad
A485. i'm not sure why, but the same thing was done in 3d56a0fc4645
for Macv45.
nick
some control transactions can confuse the xhci controller so
much that it even fails to respond to command abort or STOPEP
control command. with no way for us to abort the transaction
but a full controller reset.
we give the controller 5 seconds to abort our initial
transaction and if that fails we wake the recover process
to reset the controller.
thanks mischief for testing.
the temporary stack segment used to be at a fixed address above or
below the user stack. these days, the temp stack is mapped dynamically
by sysexec so TSTKTOP is obsolete.
between being commited to a machno and having acquired the lock, the
scheduler could come in an schedule us on a different processor. the
solution is to have dtmachlock() take a special -1 argument to mean
"current mach" and return the actual mach number after the lock has
been acquired and interrupts being disabled.
using ~IP_DF mask to select offset and "more fragments" bits
includes the evil bit 15. so instead define a constant IP_FO
for the fragment offset bits and use (IP_MF|IP_FO). that way
the evil bit gets ignored and doesnt cause any useless calls
to ipreassemble().
tested on a t43 with igfx and a 1600x1200 t43p screen
what works: lvds, blanking
what doesn't: hwgc (not visible), snarfing edid
untested: vga
based on realemu traces.
unfraglen() had the side effect that it would always copy the
nexthdr field from the fragment header to the previous nexthdr
field. this is fine when we reassemble packets but breaks
fragments that we want to just forward unchanged.
given that we now keep the block size consistent with the
ip packet size, the variable header part of the ip packet
is just: BLEN(bp) - fp->flen == fp->hlen.
fix bug in ip6reassemble() in the non-fragmented case:
reload ih after ip header was moved before writing ih->ploadlen.
use concatbloc() instead of pullupblock().
some protocols assume that Ip4hdr.length[] and Ip6hdr.ploadlen[]
are valid and not out of range within the block but this has
not been verified. also, the ipv4 and ipv6 headers can have variable
length options, which was not considered in the fragmentation and
reassembly code.
to make this sane, ipiput4() and ipiput6() now verify that everything
is in range and trims to block to the expected size before it does
any further processing. now blocklen() and Ip4hdr.length[] are conistent.
ipoput4() and ipoput6() are simpler now, as they can rely on
blocklen() only, not having a special routing case.
ip fragmentation reassembly has to consider that fragments could
arrive with different ip header options, so we store the header+option
size in new Ipfrag.hlen field.
unfraglen() has to make sure not to run past the buffer, and hadle
the case when it encounters multiple fragment headers.
all screen implementations use a Memimage* internally
for the framebuffer, so we can return a shared reference
to its Memdata structure in attachscreen() instead of
a framebuffer data pointer.
this eleminates the softscreen == 0xa110c hack as we
always use shared Memdata* now.
Under the normal close sequence, when we receive a FIN|ACK, we enter
TIME-WAIT and respond to that LAST-ACK with an ACK. Our TCP stack would
send an ACK in response to *any* ACK, which included FIN|ACK but also
included regular ACKs. (Or PSH|ACKs, which is what we were actually
getting/sending).
That was more ACKs than is necessary and results in an endless ACK storm
if we were under the simultaneous close sequence. In that scenario,
both sides of a connection are in TIME-WAIT. Both sides receive
FIN|ACK, and both respond with an ACK. Then both sides receive *those*
ACKs, and respond again. This continues until the TIME-WAIT wait period
elapses and each side's TCP timers (in the Plan 9 / Akaros case) shut
down.
The fix for this is to only respond to a FIN|ACK when we are in TIME-WAIT.
always start the pager kproc in swapinit(), simplifying kickpager().
allow zero conf.nswap and conf.nswppo. avoid allocating the reference
map and iolist arrays in that case.
use ulong for ioptr and iolist indices.
don't panic when writing pages out to the swapfile fails. just
requeue the page in the io transaction list so we will try
again next time executeio() is run or just free the page when
the swap reference was dropped.
remove unused pagersummary() function.
the FCA registers 0x28, 0x2C have been reassigned to
to FEXTNVM on i217, i218 and i219 so add Fnofca flag
and avoid writing the registers.
make link detection more robust on i217 by delaying the
phy status read after link status change by 150ms. we'd
otherwise get a "phy wedged" (power saving state?) and
not update the link status until the next link change.
the max packet size is configured in 1K increments on these chips,
which can result in the card receiving a 10K packet but the
driver having only allocated 9.5K of buffer. this actually caued
pool corruption with i210, i217, i218, i219, i350.
for 82598 and x550, we explicitely round rbsz to avoid similar bugs
in the future, even tho the Rbsz constant was already a multiple of
1K and is not affected by the bug.
segclock() has to be called from hzclock(), otherwise
only processes running on cpu0 would catche the interrupt
and the time delta would be wrong.
lock the segment when allocating Seg->profile as
profile ctl might be issued from multiple processes.
Proc->debug qlock is not sufficient.
Seg->profile can never be freed or reallocated once
set as the timer interrupt accesses it without any
locking.
instead of having application processors spin in mpshutdown()
with mmu on, and be subject to reboot() overriding kernel text
and modifying page tables, park the application processors in
rebootcode idle loop with the mmu off.
linux will send small, unpadded arp packets which may arrive over
wifi, so allow small packets into the bridge and pad any packets that
are too small when going out.
coproc.c generated the instrucitons anew each time,
requiering a i+d cache flush for each operation.
instead, we can speed this up like this:
given that the coprocessor registers are per cpu, we can
assume that interrupts have already been disabled by
the caller to prevent a process switch to another cpu.
we cache the instructions generated in a static append
only buffer and maintain separate end pointers for each
cpu.
the cache flushes only need to be done when new
operations have been added to the buffer.
reference: https://github.com/raspberrypi/firmware/issues/542
procsave(Proc* p)
{
uvlong t;
cycles(&t);
p->pcycles += t;
// TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
fpuprocsave(p);
/*
* Prevent the following scenario:
* pX sleeps on cpuA, leaving its page tables in mmul1
* pX wakes up on cpuB, and exits, freeing its page tables
* pY on cpuB allocates a freed page table page and overwrites with data
* cpuA takes an interrupt, and is now running with bad page tables
* In theory this shouldn't hurt because only user address space tables
* are affected, and mmuswitch will clear mmul1 before a user process is
* dispatched. But empirically it correlates with weird problems, eg
* resetting of the core clock at 0x4000001C which confuses local timers.
*/
if(conf.nmach > 1)
mmuswitch(nil);
}