the code used P_Random()-P_Random() in some places which has
undefined evaluation order resulting in the wrong pseudo random
numbers being returned causing demo playback to desync.
this change adds P_Random2() function which returns the right
delta-random number and uses it in place of P_Random()-P_Random()
expression.
yoann padioleaus report on 9fans:
> I think I’ve found a bug in the network stack.
> in 9/ip/ip.h there is
> struct Ipht
> {
> Lock;
> Iphash *tab[Nipht];
> };
>
> where Night is 521,
>
> but then in 9/ip/ipaux.c there is
>
> ulong
> iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
> {
> return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
> }
>
> where Nhash is just 64,
prevent double sleep():
callers to sleep() need to be serialized as there can only
be one process sleeping at a time. plrlock and plwlock do
this.
wait for dma to complete in plwrite():
we have to wait for the dma to complete before touching
plbuf again.
maintain COPEN flag in archopen()/archclose():
when open fails because it was in use, clear the COPEN
flag, so archclose() wont screw stuff up.
try the handle buffer in reverse order looking for plan9.ini
to find plan9 partition (9fat). when that fails, we'll default
to the first handle which should be the esp.
there where two problems with blank (-b flag):
we did not update the backup header when there was already a valid
backup header in place. we always want to initialize a new backup header
in blank mode!
we now also check the backup header matches the primary (or the other
way arround depending on which header could be read), reporting any
mismatches and restoring the backup from the data of the primary.
the protective mbr needs to start at sector 1 not 0 (apparently, this
matters for ovmf).
efi systems may use traditional dos partition table
with an esp (efi system partition). otherwise, honor
the protective mbr partition (0xEE) and exit when we
encounter it.
- make sure disk file is an actual file and not a directory, log or empty file
- sanity check: file has to be at least one sector to be a disk
- simplify error handling using freedisk()
- make UU() shorter by using long long constant to encode node field
- store Flag as a mask, not as a shift count
- put the attributes before the name in cmdsum() as it is fixed length
often, documents specify charsets but are really utf-8 encoded.
we now try to decode as utf-8 and only if that fails assume
the charset specified in the document.
make digest_certinfo() return the digest length, otherwise
return -1 as an error and handle it in the callers.
pass expected digest length to verify_signature() and
check digest length from certificate! make sure we wont
run off the buffer.
fix newlines in error prints of X509dump().
this implements SHA2 (224, 256, 384, 512) signature algorithms and
uses sha256WithRSAEncryption for X509req() and X509gen() instead
of oid_md5WithRSAEncryption.
the compiler used to skip zero initialization when initializer
list was given not covering unspecified elements. now we zero
all non explicitely initialized elements. for example:
typedef struct F F;
struct F
{
int a;
int b;
int c;
};
void
main(void)
{
char a[16] = { 1, 2, 3 }; /* a[3..15] initialized to zero */
F f = { .b = 1 }; /* f.a, f.c initialized to zero */
}
the emited code that initializes local variables did not handle
unaligned data causing stack corruption, affecting code like:
void main(void)
{
char a[9] = {0};
}
this change will emit code that does byte stores for the unaligned
bytes and also handles small objects (<= 16 bytes) without branches.
tlsClient() now can optionally send the server_name in the ClientHello
message by setting the TLSconn.serverName. This is required for some
https sites.
using /proc/$pid/mem to access vga bios is not portable and crashes
sgi machines when aux/vga is run. instead, try /dev/realmodemem
first (provided by realemu), then #v/vgabios.
this allows extracting tar archives that use longnames extension,
where the real filename is stored in a special entry with
linkflag == 'L' before the file entry. also skip longlink entries
with linkflag == 'K'.
David du Colombier wrote:
> The slowness issue only appears on the loopback, because
> it provides a 16384 MTU.
>
> There is an old bug in the Plan 9 TCP stack, were the TCP
> MSS doesn't take account the MTU for incoming connections.
>
> I originally fixed this issue in January 2015 for the Plan 9
> port on Google Compute Engine. On GCE, there is an unusual
> 1460 MTU.
>
> The Plan 9 TCP stack defines a default 1460 MSS corresponding
> to a 1500 MTU. Then, the MSS is fixed according to the MTU
> for outgoing connections, but not incoming connections.
>
> On GCE, this issue leads to IP fragmentation, but GCE didn't
> handle IP fragmentation properly, so the connections
> were dropped.
>
> On the loopback medium, I suppose this is the opposite issue.
> Since the TCP stack didn't fix the MSS in the incoming
> connection, the programs sent multiple small 1500 bytes
> IP packets instead of large 16384 IP packets, but I don't
> know why it leads to such a slowdown.
i made a mistake here as this change breaks the arm and mips compilers
which lack an optimiation in xcom() that folds constant pointer arithmetic
into the offset. on arm, the a node is a complex expression with op OADD of
type TIND but the test rejected the (valid) pointer arithmetic.
instead, we now test for the operations which cannot be constant instead
of using the type as a proxy.
mischief spotted that the only way for listeners to go away was
truncating (but not removing) a service script. this is wrong and
not as described in the manpage.
this change makes removing (or truncating) a listen script stop
the listener.
scandir() first marks all current announces, then reads the service
directory adding announces which will clear the marks for the ones
already there or add a new unmarked one. finally, we shoot down and
remove all still marked announces.
6c changed "- cmd_lagest_size + 1" into a *unsigned* 32bit constant. which
got added to 64bit pointer making pcb->limit > pcb->end resulting
in errors for partial commands in the buffer. removing the parentesis
propagates the operation to 64bit.
the intend of posting a note to the faulting process is to
interrupt the syscall to give the note handler a chance
to handle it. kernel processes however, have no note handlers
and all the postnote() does is set up->notepending which will
make the next attempt to sleep raise an Eintr[] error. this
is harmless, but usually not what we want.
there's no need to waste space for a error buffer in the Segio
structure, as the segmentio kproc will be waiting for the next
command after an error and will not overwite it until we issue
another command.
devproc's procctlmemio() did not handle physical segment
types correctly, as it assumed it can just kmap() the page
in question and write to it. physical segments however
need to be mapped uncached but kmap() will always map
cached as it assumes normal memory. on some machines with
aliasing memory with different cache attributes
leads to undefined behaviour!
we borrow the code from devsegment and provide a generic
segio() function to read and write user segments which
handles all the cases without using kmap by just spawning
a kproc that attaches the segment that needs to be read
from or written to. fault() will setup the right mmu
attributes for us. it will also properly flush pages for
segments that maintain instruction cache when written.
however, tlb's have to be flushed separately.
segio() is used for devsegment and devproc now, which
also allows for simplification of fixfault() as there is no
special error handling case anymore as fixfault() is now
called from faulting process *only*.
reads from /proc/$pid/mem can now span multiple pages.
code like "return g->dlen;" is wrong as we do not hold the
qlock of the global segment. another process could come in
and override g->dlen making us return the wrong byte count.
avoid copying when we already got a kernel address (kernel memory
is the same on processes) which is the case with bread()/bwrite().
this is the same optimization that devsd does.
also avoid allocating/freeing and copying while holding the qlock.
when we copy to/from user memory, we might fault preventing
others from accessing the segment while fault handling is in
progress.
walking the freelist for every page is too slow. as we
are freeing a range, we can do a single pass unlinking all
pages in our range and at the end, check if all pages
where freed, if not put the pages that we did free back
and retry, otherwise we'r done.
fixed segments are continuous in physical memory but
allocated in user pages. unlike shared segments, they
are not allocated on demand but the pages are allocated
on creation time (devsegment). fixed segments are
never swapped out, segfreed or resized and can only be
destroyed as a whole.
the physical base address can be discovered by userspace
reading the ctl file in devsegment.
when we trim the front of a block with freefromfront(),
the block magic of the back was not initialized which
could sometimes trigger the assert in blocksetsize()
to fail. fix is to just move the initialization of the
magic field before the blocksetsize() call.
the second b->magic = UNALLOC_MAGIC isnt really required
but just done for consistency with the trim() code above.
when we get an i/o error, always call hdrecover() which
will reset the port and reinitialize the interface of
the calling processes endpoint.
handle the case when we have multi-function device with
multiple reader procs in hdrecover(). the sequence is
as follows:
1) any of the reader procs encounters i/o error and calls hdrecover(),
acquires qlock and initiates port reset.
2) any other readerprocs will now encounter i/o error (due to reset) and also call
hdrecover() but will be waiting on the qlock for reset to complete.
3) first process completes reset and reinitializes its interface with setproto()
and then releases the qlock for the other readers todo the same.
this avoids listing the upper half of 64-bit membars
in Pcidev.mem[] array avoiding potential confusion
in drivers.
we also check if the upper half is programmed to zero
by bios and otherwise zap the entry in Pcidev.mem[]
and print a warning.
qemu puts multiboot data after the end of the kernel image, so
to be able to KADDR() that memory early, we extend the initial
identity mapping by 16K. right now we just got lucky with
the pc kernel as it rounds the map to 4MB pages.
when we switch to graphics mode, we do not want graphical arcs console
to print on the screen anymore as it assumes 8bit color mode and just
messes up the screen on kernel prints.
fixes bug with libmemdraw where the linker would hoist
the final ADD $const, SP at the end over loads from the
stack causing the front to fall off once a interrupt hits.
GEVector() saves the exception return PC in Ureg.r27 which needs
to be preserved.
there should be no reason for the user to change the status
register from noted() eigther, so we now just use setregisters()
in noted() to restore previous general purpose registers. this
means that CU1 will always be off after noted() because notify()
has disabled the FPU on entry and set fpstatus to FPinactive
if it was on. once user starts using FPU again, it will trap and
restore fpu registers.
touching transmit descriptors while dma is running causes the
front to fall off. new approach keeps a counter of free
descriptors in the Ring structure that is incremented
by txintr() when transmit completed.
txintr() will clean descriptors once dma has stopped and
restart dma when there are more descrtors in the chain.
this provides basic console support using the ARC bios routines
theu uartarcs driver. and has native seeq ethernet driver which
was written by reading the 2ed devseq driver as i have no
documentation on the hardware. mmu and trap code is based on the
routerboard kernel.
bootmkfile will now looks for the following proto files in order
and pick the first one it finds to build the bootfs.paq file:
1) $CONF.boofs.proto (config specific)
2) bootfs.proto (kernel specific)
3) $BOOTDIR/bootfs.proto (default generic)
from the unicode-db patch readme:
command() receives a char* that is assigned to lp, which is a Rune*,
and lp is incremented later in readchar(), so each read consumed 4 bytes.
The only time command() is called is in runpcs() with bkpt->comm,
which is a char* built in subpcs through a char*, so the string stored in
bkpt->comm was not a Rune string. A way to test the bug is:
db program
main:b argv/X
:r
the mount cache uses Page.va to store cached range offset and
limit, but mips kernel uses cache index bits from Page.va to
maintain page coloring. Page.va was not initialized by auxpage().
this change removes auxpage() which was primarily used only
by the mount cache and use newpage() with cache file offset
page as va so we will get a page of the right color.
mount cache keeps the index bits intact by only using the top
and buttom PGSHIFT bits of Page.va for the range offset/limit.
when we are skipping a process because we could not acquire
its segment lock, dont call reclaim() again (which is pointless
as we didnt pageout any pages), instead try the next process.
the Pte.last pointer is inclusive, so don't miss the last page
in pageout().
when building bootfs in d770 mode directory, the other permissions
in bootfs paq are masked off which results in boot to fail. theres
no point in checking group/other permissions on boot, so just disable
permissin checking in paqfs with the -a flag.
the special sencodefmt() in ndb/dn.c is only used with %H format for
hexadecimal printing for binary strings. removing the unused
calls to enc32() and enc64() reduces the code size by arround 4K.
(this is usefull for ndb/getip which gets linked into the kernel).
the approximation of n*2 to calculate the number of output bytes
for enc64() fails for inputs of size < 3. this is fixed by using
encodefmt() which gets the calculation right and also simplifies
the code avoiding the allocation and freeing of intermediate string
buffers.
mcountseg(), mfreeseg():
use Pte.first/last pointers when possible and avoid constructs
like s->map[i]->pages[j].
freepte():
do not zero entries in freepte(), the segment is going away and
here is no point in zeroing page pointers. hoist common code at
the top avoiding duplication.
segpage(), fixfault():
avoid load after store for Pte** pointer.
fixfault():
return -1 in default case to avoid the "used but not set" warning
for mmuphys and get rid of the useless initialization.
syssegflush():
due to len being unsigned, the pe = PGROUND(pe) can make "chunk"
bigger than len causing a overflow. rewrite the function and deal
with page alignment and errors at the beginning.
syssegflush(), segpage(), fixfault(), putseg(), relocateseg(),
mcountseg(), mfreeseg():
keep naming consistent.
the "to" address can overflow in syssegfree() causing wrong
number of pages to be passed to mfreeseg(). with the current
implementation of mfreeseg() however, this doesnt cause any
data corruption but was just freeing an unexpected number of
pages.
this change checks for this condition in syssegfree() and
errors out instead. also mfreeseg() was changed to take
ulong argument for number of pages instead of int to keep
it consistent with other routines that work with page counts.
sdbio() tests if it can pass the buffer pointer directly to
the driver when it is already in kernel memory. we also need
to check if the buffer is properly aligned but alignment
requirement is handled in system specific sdmalloc() and
was not known to devsd.
to solve this, we *always* page align sd buffers and get rid
of the system specific sdmalloc() macro (was only used in bcm
kernel).
chaninit() does not initialize Chan.qentry and Chan.nentry
and there is no way to get rid of such a channel. nobody is
using it, so removing the function to avoid confusion.
ignore physical segments in mcountseg() and mfreeseg(). physical
segments are not backed by user pages, and doing putpage() on
physical segment pages in mfreeseg() is an error.
do now allow physical segemnts to be resized. the segment size
is only checked in segattach() to be within the physical segment!
ignore physical segments in portcountpagerefs() as pagenumber()
does not work on the malloced page structures of a physical segment.
get rid of Physseg.pgalloc() and Physseg.pgfree() indirection as
this was never used and if theres a need to do more efficient
allocation, it should be done in a portable way.
it is possible to have fonts belong to different or no display, so the
check for defaultsubfont has to be against font->display, not the global
display variable.
remove unused freeup() routine.
handle strdup() error in allocsubfont() and realloc() error in buildfont().
the namespace might be shared by other processes. instead, we
create a anonymous pipe with pipe() and use devdup to open one
end close-on-exec. this is shorter and avoids the race condition.
do not touch Execargs after writing the error message as the
process might be gone after the write. this was to manually
close the fd which isnt neccesary as the kernel will do it
for us on the following exit.
rebuilding the xref table does not work for pdfs with
compressed object streams. as a work arround, we skip
xref table verification and ignore wrong xref gen #
for gen 0 objects.
convert:
x = B || W
MOVxLZX a, r; MOVxQZX r, b -> MOVxQZX a, r; MOVQ r, b
MOVxLSX a, r; MOVxQSX r, r -> MOVxQSX a, r; MOVQ r, r
the MOVQ can then be eleminated by copy propagation.
improve subprop() by accepting other mov and lea
instructions as the source op.
tlsServer() closes the passed in fd, in our case fd=1 leaving it
with no std output which got occupied by pipe() filedescriptor
which it then closed after duping... a classic.
delete all this mess. theres no reason to fork() and copy traffic
on a pipe at all as tlsServer() gives us a perfectly valid filedescriptor.
just dup() and exec() and we'r done.
the imported wc from sources is arround 8 times slower
than our old one. it is common to run wc on large log files
to count lines. so i think the implementation complexity
is justified. (just like with grep)
the following hooks have been added to the ehci Ctlr
structore to handle cache coherency (on arm):
void* (*tdalloc)(ulong,int,ulong);
void* (*dmaalloc)(ulong);
void (*dmafree)(void*);
void (*dmaflush)(int,void*,ulong);
tdalloc() is used to allocate descriptors and the periodic
frame schedule array. on arm, this needs to return uncached
memory. tdalloc()ed memory is never freed.
dmaalloc()/dmafree() is used for io buffers. this can return
cached memory when when hardware maintains cache coherency (pc)
or dmaflush() is provided to flush/invalidate the cache (zynq),
otherwise needs to return uncached memory.
dmaflush() is used to flush/invalidate the cache. the first
argument tells us if we need to flush (non zero) or
invalidate (zero).
uncached.h is gone now. this change makes the handling explicit.
map the whole ocm memory on boot so we can translate physical to
virtual addresses and back for uncached memory using KADDR() and
PADDR().
replace ualloc() with ucalloc() returning virtual address. physical
address can be acquired with PADDR() now.
as ocm is now always mapped, use KADDR() instead of tmpmap() for
mp bootstrap.
passing "", "." or ".." as name caused a crash in
getenv() as it would open the directory; then seek()
to determine the file size would fail and return -1.
now checking for these special names and set
error string when its bad.
doing a single read() will not work when /env has a
9p fileserver mounted onto it and the file size is bigger
than the i/o unit. so doing incremental reads until
we get eof.
there are no kernels currently that do page coloring,
so the only use of cachectl[] is flushing the icache
(on arm and ppc).
on pc64, cachectl consumes 32 bytes in each page resulting
in over 200 megabytes of overhead for 32gb of ram with 4K
pages.
this change removes cachectl[] and adds txtflush ulong
that is set to ~0 by pio() to instruct putmmu() to flush
the icache.
vbs/vbe members in Mode was only used in the vesadb
and cannot be changed from vgadb.
use shs/ehs in drivers when refering to the horizontal
sync pulse. clarify the matter in a comment.
link detailed timing modes at the head of the edid
modelist. these are the modes we'r interested in,
not the ones from vesadb.
igfx and vesa can determine monitor timing information from ddc
and store the edid info for connected monitors in vga->edid[].
when monitor type cannot be found in vgadb, we consult the edid
information and make a mode based on the edid info.
this avoids having to maintain a vgadb entry for each monitor.
monitor can be set to "[width]x[height]@[freq]Hz" for a specific
edid setting. when not found, a mode is searched based on the
size.
so the following should work:
aux/vga -m 1366x768@60Hz -l 1366x768x32
aux/vga -m auto -l 1366x768x32
dbvesamode() modified the passed in size string in the process
of option parsing. this is a no-go because the string might be
constant in the read only section. provide cracksize() function
for the parsing and make a static copy.
do the vendor specific monitor detection in vbesnarf() instead
of vbecheck(). vbecheck()'s purpose is to check if vesa bios
service is avialable, not snarf graphics card state.
nvidiascale() was a no-op because it missed the vbecall() at
the end of the function. this means it was never tested so i
add the missing vbecall(), but disable nvidiascale for now
until someone tests this.
keep fancy stuff out of the Vbe structure. it is just there for
making bios calls, not keep state about the graphics card.
we used to read beyond the boundaries of the becon because of
the end pointer was offset by the beacon header. this is
also what caused the double entries.
this bug happens when the kernel runs out of mount rpc
buffers when allocating a flush rpc. in this case, mntflushalloc()
will errorjump out of mountio() leaving the currently in
flight rpc in the mount. the caller of mountrpc()/mountio()
frees the rpc thats still queued in the mount leaving
to interesting results.
for the fix, we add a waserror() arround mntflushalloc() and
handle the error case like a mount rpc failure which will
properly dequeue the rpc's in flight.
this adds support for eap-peap/mschapv2 and eap-ttls/pap.
code has only been tested with freeradius and a cheap
access point, not tested with actual eduroam network.
this is used for wpa2 enterprise peap/mschapv2. server role
is not implemented as that would require changing the
wire format on the auth server.
the naming is unfortunate as we already have proto=mschap2 which
really refers to ntlmv2.
the FPOFF macro that follows the FXSAVE/FSAVE instructions in l.s
used to execute WAIT instruction when the TS flag was not set. this
is wrong and causes pending exceptions to be raised from fpsave which
is called from provsave() which holds up->rlock making it deadlock
when matherror() tries to postnote() to itself.
so making FPOFF non-waiting (just set TS flag).
we handle pending exception when restoring the context.
program secret plane size and position registers described as "reserved"
in g45_vol_3_register_0_0.pdf that was found by inspecting vesa bios
port traces.
also, we have to set 18:19 (Cursor/Dispaly/Overlay Planes Off) in
PIPExCONF while programming the planes on this card. this is what
vesa bios does on modeset.
avoid sync the jar file when fids get clunked.
the only reason to sync the jar on clunk is when it has
been marked dirty (cookies added or deleted) and we
want to flush the changes to disk.
- rewrite when jar->dirty != 0 (caller modified the in memory jar)
- reread when the jar->qid != stat(jar->file)->qid (on disk file changed)
- ignore deleted cookies in cookiesearch()