When enumerating processes, the `find_process()` process didn't consult
whether a process was actually free. This resulted in a crash,
particularly when attaching a debugger to a crashed process.
Signed-off-by: Sean Cross <sean@xobs.io>
This command ensures memory is all owned by the correct process and is
unique in its ownership.
It takes a long time to run, so ensure the watchdog timer is disabled.
Signed-off-by: Sean Cross <sean@xobs.io>
Add a function to ensure mappings are unique across the whole system.
This takes a very long time and can crash if the watchdog timer isn't
paused.
Signed-off-by: Sean Cross <sean@xobs.io>
The phys_to_virt function can be used to determine what physical address
page is mapped to a virtual address page.
This throws an error when a page is mapped twice, which shouldn't
happen.
Signed-off-by: Sean Cross <sean@xobs.io>
The kernel stack offset should be aligned to 16 bytes. Previously it was
aligned to 8 bytes. It's unclear if this was the cause of any issues,
but it is best practice to keep things aligned to 16 bytes.
As part of this, key the atomic instructions off of the CPP macro
presence of atomic instructions.
Signed-off-by: Sean Cross <sean@xobs.io>
Fix memory zeroing when requesting a physical pointer. Previously, only
the first 25% of a page was zeroed due to a bug when casting between
*mut u8 and *mut usize.
This now uses `write_volatile` to ensure the memory clear isn't
optimized out, and uses `usize` pointers everywhere.
Signed-off-by: Sean Cross <sean@xobs.io>
The register set should be cleared already, however it is possible
(though remote) that register values are not cleared when a thread is
created.
Ordinarily threads are zeroed when destroyed, but this makes sure
they're zeroed upon creation as well.
Signed-off-by: Sean Cross <sean@xobs.io>
While it would be nice if we stopped the PLLs as we do on hardware,
Renode does not yet have the ability to issue the `wfi` instruction from
a peripheral write.
As such, directly call `wfi()` on Renode similar to how Cramium
operates.
Signed-off-by: Sean Cross <sean@xobs.io>
using the DUART means we don't get console input on the kernel
(because the DUART is incapable of this) but it's a decent compromise
I think because the DUART is fast and efficient, and mostly we want
it to capture kps?
Eventually we'll need an input mode but for now, this will get us
moving.
Mark `MemoryRange::as_slice()` and `MemoryRange::as_slice_mut()` as
unsafe.
This is due to the fact that not all representable types can be cast to
an arbitrary value. For example, if Process A sends random values to
Process B, then Process B casts the memory to a slice of `bool`, then
any values that are not 0 or 1 are undefined.
Because these functions can leak UB into the program, they are marked as
unsafe.
This patch adds `unsafe {}` blocks to all instances where this function
is called. Additionally, all instances have been checked to verify that
they do not cast to any invalid types -- most use `u8` or `u32`.
Additionally, the long-deprecated `MemoryRange::from_parts()` call was
removed, since that causes UB without being marked as unsafe.
Signed-off-by: Sean Cross <sean@xobs.io>
With Rust 1.71.0, mut detection has changed slightly, and it is more
aggressive about warning when things do not need to be mutable.
Remove these from the `services` file.
Signed-off-by: Sean Cross <sean@xobs.io>
SUpport debugging when interrupt handlers go awry, such as when they
blow out their own stack.
Do this by creating a dummy sentinal of 255 for interrupt handlers.
Signed-off-by: Sean Cross <sean@xobs.io>
When an interrupt handler panics, restore the system and allow it to
continue. This will help to debug IRQ handlers that panic for one reason
or another, such as infinite recursion.
Signed-off-by: Sean Cross <sean@xobs.io>
This changes the process.inner.pid to the correct PID. Before, it was
simply 1. This lead to problems, for example when sending messages
where an assert checks to make sure that the current PID and the
process PID are the same. Now, you can send messages from a new process.
- make the "base" field no longer public. It is accessible, but only
through an `unsafe` method, because, it is unsafe.
- add accessors to offest/mask fields. Because, it's not at all
unsafe to access these, and it can be useful for bit-ops that are
not part of the generic set of UTRA.
- add Arc to AtomicCSR, and require `std` for AtomicCSR types.
This should not break anything, I checked inside @foundation-devices
keyOS and they don't seem to be using AtomicCSR anywhere.
The Arc makes it a bit safer to clone the AtomicCSR base pointer
and share it between threads, but it will have an impact on performance.
The USB stack (which requires AtomicCSR) was regression testing and the
impact seems minimal.
Recall that the main purpose of AtomicCSR is to provide a CSR accessor
that does not require a mutable reference to the base object. This
can make certain Rust idioms a bit cleaner. We wrap the base accessor
in Arc+Atomic to try and improve the safety of throwing the borrow
checker under the bus, but it's still not perfect because hardware
mutable state can have side-effects within hardware itself that cannot
be modeled or checked by Rust's borrow checker.
Instead of always doing bytewise accesses, support 2- and 4-byte access.
Additionally, recognize when multiple 4-byte reads are required.
Note that an additional optimization may be made here in the future to
prevent having to check every address, but this is left for a future
optimization.
Signed-off-by: Sean Cross <sean@xobs.io>
Instead of remapping the page to allow the kernel to access a process'
memory, simply set the SUM bit. This makes it no longer an error for the
kernel to access userspace.
Keep setting the `W` bit when we poke, to allow for updating program
memory with breakpoints.
Signed-off-by: Sean Cross <sean@xobs.io>
Previously, we were creating a fake interrupt that was a "user software
interrupt". Update this to be a "supervisor external interrupt" to fix
hardware resume.
Signed-off-by: Sean Cross <sean@xobs.io>
Debug handling was not correct, and didn't work at all. Additionally,
interrupt masking didn't work.
Fix these problems.
Signed-off-by: Sean Cross <sean@xobs.io>
Implement the basics required to get "extended mode" working. This is
waiting on upstream to fix issues, but should allow us to attach to
processes once it works.
Signed-off-by: Sean Cross <sean@xobs.io>
When debugging an invalid process (e.g. not yet run, terminated, etc.)
return an error rather than silently continuing.
Signed-off-by: Sean Cross <sean@xobs.io>
Disable IRQs during destruction, but only if constructed with
`GdbUart::new()`. This allows characters to buffer when the GDB bridge
is destroyed while avoiding the double-free error we were getting from
creating a new UART in the IRQ handler.
Signed-off-by: Sean Cross <sean@xobs.io>
This adds a basic gdb server. Currently, it is possible to list
processes and inspect memory and threads. It is not yet possible to
actually interact with code (e.g. no breakpoints and no single
stepping).
Signed-off-by: Sean Cross <sean@xobs.io>
Add an initial reimplementation of the gdb-stub using the gdbstub
backing crate.
This supports process enumeration and basic thread investigation.
Processes will pause when the debugger is inspecting them. Memory and
registers can be investigated. Threads can be listed and selected.
It does not yet support breakpoints.
Signed-off-by: Sean Cross <sean@xobs.io>
Previously, `disable_irq()` would unconditionally mask an interrupt in
the `sim` register. However, when interrupts are disabled this register
is zero, and we really should be updating `SIM_BACKING`.
Consult the state of the interrupt handler and update the appropriate
field as necessary.
Signed-off-by: Sean Cross <sean@xobs.io>
This function never failed. Make it infallible so that it matches the
same calling convention as `enable_irq()`
Signed-off-by: Sean Cross <sean@xobs.io>
Even when the print-debug feature isn't turned on, println! macro is still able to output some critical non-debug info to the console such as panics, process crashes and violations, etc. Debugging messages are printed with klog! macro that's disabled when debug-print feature is not set.
this commit adds the facilities to extract eh_frame[_header]
sections and pass it to each process.
A bump is required to `std` to extract the passed parameters.
it works with e.g. shellchat, but not vault.
still scratching my head on what's gone wrong -- it's
crashing in the pre-boot, which means something is not
mapped right for some case that wasn't caught in the
earlier testing.
Atomic operations were previously broken. RISC-V breaks atomic
operations into multiple instructions, and there is some state kept
between those instructions. This state is not visible, and is internal
to the processor.
We were ignoring this state, which resulted in inconsistencies
throughout the system. The following sequence was possible:
1. A thread loads a value, and obtains the `reservation set`
2. A context switch happens on the following instruction
3. A different thread loads the value, modifies it, and continues
4. A third thread (or a different process) loads a value and obtains the
`reservation set`
5. The original thread runs, sees the `reservation set` is held, and
updates the value, clobbering what the second thread did in #3
A workaround for this is to perform a dummy `sc` as part of the context
switch. This invalidates any atomic operations that may be pending.
Signed-off-by: Sean Cross <sean@xobs.io>
The previous patch didn't properly restore thread IDs when switching
contexts -- there were spots where we missed things, and spots where we
were double-borrowing.
Fix these corner cases.
Signed-off-by: Sean Cross <sean@xobs.io>
Note the current thread in the original process when its quantum
expires. This will allow us to clean up after ourselves when a context
switch occurs, and will help to prevent thread starvation.
Signed-off-by: Sean Cross <sean@xobs.io>
Currently, returning a Message (e.g. a Scalar1, Scalar2, or
MemoryMessage) always results in a context switch from the server to the
client. This is what makes these syscalls cheaper.
However, this results in process starvation. For example, if three
processes send a message to a server, then the server will only be able
to respond to one of those messages at a time. This works well with a
lightly-loaded system, but quickly falls apart when many threads are
running.
Keep track of which process and thread were originally switched to as
part of the `SwitchTo` call. If the Server is responding to a message
and owns the current quantum, don't immediately switch to the Client
thread.
Signed-off-by: Sean Cross <sean@xobs.io>
For some reason, the current thread becomes 0 during suspend or resume.
This causes an error during boot.
Patch this up while we figure out what's causing it.
Signed-off-by: Sean Cross <sean@xobs.io>
Unify scalar return calls so that we only have one return path rather
than three.
We can almost unify memory returning as well, but it's not quite there.
Signed-off-by: Sean Cross <sean@xobs.io>
There were a few corner cases when it came to thread selection. Namely,
the same thread had a higher chance of repeatedly being executed.
Clean up these corner cases, and as a result get libstd tests to pass.
Signed-off-by: Sean Cross <sean@xobs.io>
Add notes on how to properly hand memory to userspace. This does not yet
work, but is committed here as a work-in-progress.
Signed-off-by: Sean Cross <sean@xobs.io>
The default mem size got shrunk down to 4 MB earlier, but there is a
lingering issue that prevents specifying virtual addresses. As a result,
pddb and others don't work.
Temporarily revert this change.
Signed-off-by: Sean Cross <sean@xobs.io>
The process search now uses iterators properly. It's still not ideal
because it needs to investigate every process, but it's better than it
was.
Signed-off-by: Sean Cross <sean@xobs.io>
Use a multiply-based algorithm to count the number of leading zeroes.
This results in a function that's just 20 instructions long.
Signed-off-by: Sean Cross <sean@xobs.io>
THe act of finding a runnable thread is so common, yet the kernel
contains three ways of doing this.
Use a unified function to select the next available thread.
Signed-off-by: Sean Cross <sean@xobs.io>
Previously the `current_thread` was set to 0, which is invalid. Set the
`current_thread` so that it defaults to the initial thread ID.
Signed-off-by: Sean Cross <sean@xobs.io>
This memory region is much smaller than the previous value of 256 MB,
but it will limit the amount of memory used by superpages in
long-running processes.
Previously, we would march through memory as messages were passed back
and forth and a process' memory space would quickly be eaten up by 1024
pages.
Signed-off-by: Sean Cross <sean@xobs.io>
When waiting on a thread, it may be the case that the thread we're
joining has exited already. In this case, the correct approach is to
resume execution rather than switching to the parent process.
This fixes an issue where `SWITCHTO_CALLER` is None when joining a
short-lived thread.
Signed-off-by: Sean Cross <sean@xobs.io>
When attempting to return an invalid item, return `DoubleFree`. This is
because such cases are most likely due to instances where a message was
responded to twice.
Signed-off-by: Sean Cross <sean@xobs.io>
- we don't need a general memset call -- just a zero page call
- use native rust semantics to embody the call. some alignment checking is
done on the arguments on the way in and out that seem worth it
- the unrolled loop doesn't pay off because we're at the limit of
write bandwidth on the CPU at this point. we would need write-back
caches to gain more performance through unrolling.
@xobs found a scheduler bug that would trigger a runnable process
search every time a scalar message returned. This fixes the problem,
causing the quantum to go back to the caller as intended.
Improves performance on the syscall by about 40%.
Fix a segfault that occurred when using ReplyAndReceiveNext on hosted
mode. This now properly passes memory messages back to the client.
Signed-off-by: Sean Cross <sean@xobs.io>
Implement `ReplyAndReceiveNext` as a syscall. This will reply to a
message, pull the next message out of the queue, and then re-queue the
server to run. This should make servers much more responsive.
This patch has been tested on both hosted and native modes.
Signed-off-by: Sean Cross <sean@xobs.io>
I've added a `platform` module to store all platform specific code, (not
architecture specific) as some platforms will require custom drivers, e.g.
for debug output and for the random number generation code. The platform
code is in charge of mapping any peripherals needed to work, also to
initialize any other parts of the kernel that require drivers, for example
the debug shell.
Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
The rationale is that xous-rs should have only architecture
specific code, e.g.: riscv, arm, x86, etc. To make other
crates that depend on it not specify the features.
This could be useful when using xous-rs with `libstd`
for example.
Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
This allows for a more reliable detection of target_os configuration
in build scripts. The target is inconsistent between some architectures,
notably armv7a is `armv7a-none-eabi` skipping the `unknown` (the vendor,
I guess) part. This happen with some of the unrelated Cortex-M targets
present, and others may also be.
Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
- strip out gdb-stub. Per xobs, the feature never worked, and it
depends upon a branch of a git repo which is not allowed by crates.io
Since the feature hasn't been developed, and crates.io will not
allow even an optional feature that points to a git repo, the feature
was stripped out.
- rename "kernel" to "xous-kernel", so that we can live in a crates.io
package namespace that is specific to Xous.
still have to figure out the riscv package issue.
this will help speed up performance profiling as we can
resolve the physical address of the performance buffer allocated
in RAM and use a USB command to read it out, instead of streaming
it over serial.
Instead of passing a constructed mutable ref from the pagetable entry,
pass a raw pointer and use `read_volatile()` / `write_volatile(x)` on
this pointer.
This should remove a little bit of UB from the kernel.
Signed-off-by: Sean Cross <sean@xobs.io>
Previously, the kernel would dutifully try to map memory that was in the
kernel space. It did this by investigating the kernel memory offset,
which immediately causes a double-fault.
Check to make sure a userspace process is not trying to map kernel
memory before checking the valid page.
Signed-off-by: Sean Cross <sean@xobs.io>
Implement the syscall to adjust a process' limit. Currently this
only supports adjusting the heap maximum and the heap size.
In order to adjust a limit, you must first present the current limit.
This can be obtained by requesting a bogus value. The current limit is
returned as part of the result.
Signed-off-by: Sean Cross <sean@xobs.io>
Return the heap size and offset when decreasing the heap. Additionally,
return the heap size when increasing the heap by 0 bytes.
Signed-off-by: Sean Cross <sean@xobs.io>
this contains a dependency to `failure` two levels down that has a critical
vulnerability. Unfortunately no new versions of debug-here have been
published in a while. It's no longer used, so just stripping it out
altogether.
Hosted mode spawns processes very differently, and this difference was
not reflected after changes were made to native mode.
Signed-off-by: Sean Cross <sean@xobs.io>
Unmap the pages from the child process after we're done setting them up.
This ensures they're not still aliased by our process, despite being
marked as "owned" by the other process.
Signed-off-by: Sean Cross <sean@xobs.io>
Implement a functioning CreateProcess syscall on riscv. This call
creates a server in the child process, and connects the server to the
parent. The parent can communicate with the child process using this
server.
The Server ID is passed as four `u32` values to the entrypoint function.
This can be reassembled into something that can then be passed to the
`ReceiveMessage` syscall.
Signed-off-by: Sean Cross <sean@xobs.io>
We now us `ProcessStartup` as the return type. This builds in tset
mode, hosted mode, and RISC-V mode.
Process Startup is still not implemented for RISC-V mode.
Signed-off-by: Sean Cross <sean@xobs.io>
Turns out we didn't end up needing this capability, so, commenting it
out because it is a shy too powerful and is like packing a live
mortar shell in a storage unit: eventually, someone is going to
get hurt, even though it seems mostly harmless at the moment.
Code just commented out in case we need this feature in the future,
but, the main reason it was asked for (the PDDB) was accomplished
without it.
This moves the kernel into the main monorepo, allowing it to share
packages with the rest of the system. This change will allow us to
reduce the number of rebuilds that take place, as well as reducing disk
usage.
Note that the loader is still an indepenent project, and the integration
of that into the monorepo is pending.
Signed-off-by: Sean Cross <sean@xobs.io>
Each Cargo.toml now includes a comment which remnids maintainers
of the dependency policy for Xous (that is, nail down every dependency
to the minor number).
Correctly handle transitions to and from exception handling.
Previously, the thread ID was incorrectly set such that the exception
handler became a valid thread. This has been adjusted so that the
exception handler is no longer considered a thread, and all other
threads will cease scheduling during this process.
Signed-off-by: Sean Cross <sean@xobs.io>
Memory is on-demand allocated, meaning it's entirely possible to
allocate and free memory without ever touching physical pages.
Previously, when we attempted to free memory, it would skip over pages
that were never backed by real memory.
With this patch, we continue to free the virtual page even if there is
no associated physical page.
Signed-off-by: Sean Cross <sean@xobs.io>
Memory is on-demand allocated, meaning it's entirely possible to
allocate and free memory without ever touching physical pages.
Previously, when we attempted to free memory, it would skip over pages
that were never backed by real memory.
With this patch, we continue to free the virtual page even if there is
no associated physical page.
Signed-off-by: Sean Cross <sean@xobs.io>