Splits UART tx/rx into separate CAmkES procedures

This ends the behavior where log messages would block on the prompt.

This change does not fix the potential race on dataports if
kata-uart-client read or write has multiple concurrent callers. A later
change will protect those using CAmkES mutexes, although the
alternative of having DebugConsole *own* the UART should also be
considered.

Change-Id: I8d5d8336cd58b9f22cca81ae6aca13b4ed57e7e4
GitOrigin-RevId: e781fd8454d22e0f829d788fe602e431551e259a
This commit is contained in:
Matt Harvey 2021-08-15 14:06:55 -07:00 committed by Sam Leffler
parent 20c83f6777
commit 7c3cc70ab1
6 changed files with 49 additions and 41 deletions

View File

@ -6,9 +6,12 @@ import <SeL4DebugInterface.camkes>;
component DebugConsole {
control;
uses uart_inf uart;
dataport Buf tx_dataport;
uses dataport_io_inf uart_tx;
dataport Buf rx_dataport;
uses dataport_io_inf uart_rx;
provides LoggerInterface logger;
uses ProcessControlInterface proc_ctrl;

View File

@ -8,8 +8,8 @@ use kata_io as io;
extern "C" {
static rx_dataport: *mut cty::c_uchar;
static tx_dataport: *mut cty::c_uchar;
fn uart_rx(n: cty::size_t);
fn uart_tx(n: cty::size_t);
fn uart_rx_update(n: cty::size_t);
fn uart_tx_update(n: cty::size_t);
}
// Console logging interface.
@ -27,7 +27,7 @@ pub struct Rx {}
impl io::Read for Rx {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
unsafe {
uart_rx(buf.len());
uart_rx_update(buf.len());
let port = core::slice::from_raw_parts(rx_dataport, buf.len());
buf.copy_from_slice(&port);
}
@ -42,7 +42,7 @@ impl io::Write for Tx {
unsafe {
let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
port.copy_from_slice(buf);
uart_tx(buf.len());
uart_tx_update(buf.len());
}
Ok(buf.len())
}

View File

@ -11,11 +11,10 @@
*/
component UartDriver {
dataport Buf mem;
dataport Buf mmio_region;
dataport Buf tx_dataport;
dataport Buf rx_dataport;
// consumes Interrupt interrupt;
provides uart_inf uart;
provides dataport_io_inf uart_rx;
provides dataport_io_inf uart_tx;
}

View File

@ -11,14 +11,14 @@
#include "opentitan/uart.h"
// Referenced by macros in the generated file opentitan/uart.h.
#define UART0_BASE_ADDR (void *)mem
#define UART0_BASE_ADDR (void *)mmio_region
// Frequency of the primary clock clk_i.
#define CLK_FIXED_FREQ_HZ (24ull * 1000 * 1000)
#define REG32(addr) *((volatile uint32_t *)(addr))
void uart__init() {
void pre_init() {
// Computes NCO value corresponding to baud rate.
// nco = 2^20 * baud / fclk (assuming NCO width is 16-bit)
uint64_t baud = 115200ull;
@ -75,7 +75,7 @@ static int uart_tx_ready() {
*/
}
void uart_rx(size_t n) {
void uart_rx_update(size_t n) {
char *c = (char *)rx_dataport;
// TODO(mattharvey): Error return value for n > PAGE_SIZE
for (size_t i = 0; i < n && i < PAGE_SIZE; ++i) {
@ -87,7 +87,7 @@ void uart_rx(size_t n) {
}
}
void uart_tx(size_t n) {
void uart_tx_update(size_t n) {
char *c = (char *)tx_dataport;
// TODO(mattharvey): Error return value for n > PAGE_SIZE
for (size_t i = 0; i < n && i < PAGE_SIZE; ++i) {

View File

@ -10,7 +10,6 @@
* @TAG(DATA61_BSD)
*/
procedure uart_inf {
void rx(in size_t n);
void tx(in size_t n);
procedure dataport_io_inf {
void update(in size_t n);
};

View File

@ -12,7 +12,7 @@
import <std_connector.camkes>;
import "interfaces/uart.idl4";
import "interfaces/dataport_io.idl4";
import "interfaces/VectorCoreInterface.camkes";
import "components/UartDriver/UartDriver.camkes";
import "components/DebugConsole/DebugConsole.camkes";
@ -23,9 +23,9 @@ import "components/VectorCoreDriver/VectorCoreDriver.camkes";
component UART {
hardware;
dataport Buf mem;
// TODO(mattharvey): Make receives wait on interrupt.
// emits Interrupt interrupt;
dataport Buf mmio_region;
emits Interrupt rx_watermark;
}
component VectorCoreHw {
@ -35,22 +35,27 @@ component VectorCoreHw {
assembly {
composition {
component UART uart;
component UartDriver drv;
component DebugConsole debug_console;
component ProcessManager process_manager;
component SeL4Debug sel4debug;
component VectorCoreHw vctop;
component VectorCoreDriver vc_drv;
component UART uart;
component UartDriver uart_driver;
component ProcessManager process_manager;
component MlCoordinator ml_coordinator;
component DebugConsole debug_console;
connection seL4HardwareMMIO uart_mem(from drv.mem, to uart.mem);
connection seL4HardwareMMIO vc_csr(from vc_drv.csr, to vctop.csr);
// UartDriver
connection seL4HardwareMMIO uart_mem(from uart_driver.mmio_region,
to uart.mmio_region);
// TODO(mattharvey): Make receives wait on interrupt.
// connection seL4HardwareInterrupt uart_interrupt(
// from uart.interrupt, to drv.interrupt);
connection seL4RPCCall uart_inf(from debug_console.uart, to drv.uart);
// VectorCoreDriver
connection seL4HardwareMMIO vc_csr(from vc_drv.csr, to vctop.csr);
connection seL4RPCCall VectorCoreInterface(from ml_coordinator.vctop,
to vc_drv.vctop);
// Hookup ProcessManager to DebugConsole for shell commands.
connection seL4RPCCall ProcessControlInterface(from debug_console.proc_ctrl,
@ -58,6 +63,16 @@ assembly {
connection seL4RPCCall PackageManagerInterface(from debug_console.pkg_mgmt,
to process_manager.pkg_mgmt);
// Connect the DebugConsole to the UartDriver.
connection seL4SharedData tx_channel(
from debug_console.tx_dataport, to uart_driver.tx_dataport);
connection seL4RPCCall tx_call(
from debug_console.uart_tx, to uart_driver.uart_tx);
connection seL4SharedData rx_channel(
from debug_console.rx_dataport, to uart_driver.rx_dataport);
connection seL4RPCCall rx_call(
from debug_console.uart_rx, to uart_driver.uart_rx);
// Connect the LoggerInterface to each component that needs to log
// to the console.
connection seL4RPCCall LoggerInterface(from process_manager.logger,
@ -72,25 +87,17 @@ assembly {
connection seL4RPCCall MlCoordinatorInterface(from debug_console.mlcoord,
to ml_coordinator.mlcoord);
connection seL4RPCCall VectorCoreInterface(from ml_coordinator.vctop, to vc_drv.vctop);
connection seL4SharedData tx_channel(
from debug_console.tx_dataport, to drv.tx_dataport);
connection seL4SharedData rx_channel(
from debug_console.rx_dataport, to drv.rx_dataport);
}
configuration {
uart.mem_paddr = 0x40031000;
uart.mem_size = 0x1000;
// seL4 claims 10 is bigger than irqMax if this is uncommented.
// uart.interrupt_irq_number = 10;
uart.mmio_region_paddr = 0x40031000;
uart.mmio_region_size = 0x1000;
vctop.csr_paddr = 0x48000000;
vctop.csr_size = 0x1000;
random.ID = 1;
uart.integrity_label = "drv";
uart.integrity_label = "uart_driver";
}
}