hv: debug: Convert PCI UART paramter from a BDF string to a hex value

BDF string can be parsed by the configuration tool. A 16bit WORD value with
format (B:8, D:5, F:3) can be passed from configuration to the
hypervisor directly to save some BDF string parse code.

Tracked-On: #4937
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Shuo A Liu 2020-08-27 17:45:19 +08:00 committed by wenlingz
parent 9af694dfbc
commit d6b9682581
3 changed files with 19 additions and 50 deletions

View File

@ -134,11 +134,12 @@ config SERIAL_MMIO
endchoice endchoice
config SERIAL_PCI_BDF config SERIAL_PCI_BDF
string "BDF of serial PCI device" hex "BDF of serial PCI device"
depends on SERIAL_PCI depends on SERIAL_PCI
default "0:18.2" default 0x00c2
help help
BDF: bus, device and function of the serial PCI device; for an example, BDF: bus, device and function of the serial PCI device. The BDF is packed
into a 16bit WORD with format (B:8, D:5, F:3). For an example,
PCI device ttyS2: 0:18.2. PCI device ttyS2: 0:18.2.
config SERIAL_PIO_BASE config SERIAL_PIO_BASE

View File

@ -28,6 +28,7 @@ static struct uart_cmd {
bool handle_dbg_cmd(const char *cmd, int32_t len) bool handle_dbg_cmd(const char *cmd, int32_t len)
{ {
uint32_t i; uint32_t i;
uint64_t data;
for (i = 0; i < ARRAY_SIZE(cmd_list); i++) { for (i = 0; i < ARRAY_SIZE(cmd_list); i++) {
int32_t tmp = strnlen_s(cmd_list[i].str, MAX_CMD_LEN); int32_t tmp = strnlen_s(cmd_list[i].str, MAX_CMD_LEN);
@ -44,18 +45,16 @@ bool handle_dbg_cmd(const char *cmd, int32_t len)
/* set uart disabled*/ /* set uart disabled*/
uart16550_set_property(false, type, 0UL); uart16550_set_property(false, type, 0UL);
} else if (type == PIO) { } else if (type == PIO) {
uint64_t addr = strtoul_hex(cmd + tmp); data = strtoul_hex(cmd + tmp);
if (addr > MAX_PORT) { if (data > MAX_PORT) {
addr = DEFAULT_UART_PORT; data = DEFAULT_UART_PORT;
} }
uart16550_set_property(true, type, addr); uart16550_set_property(true, type, data);
} else if (type == PCI) {
uart16550_set_property(true, type, (uint64_t)(cmd+tmp));
} else { } else {
uint64_t addr = strtoul_hex(cmd + tmp); data = strtoul_hex(cmd + tmp);
uart16550_set_property(true, type, addr); uart16550_set_property(true, type, data);
} }
} }

View File

@ -20,6 +20,7 @@ struct console_uart {
enum serial_dev_type type; enum serial_dev_type type;
union { union {
uint16_t port_address; uint16_t port_address;
union pci_bdf bdf;
void *mmio_base_vaddr; void *mmio_base_vaddr;
}; };
@ -36,14 +37,13 @@ static struct console_uart uart = {
.port_address = CONFIG_SERIAL_PIO_BASE, .port_address = CONFIG_SERIAL_PIO_BASE,
.reg_width = 1, .reg_width = 1,
}; };
static char pci_bdf_info[MAX_BDF_LEN + 1U];
#elif defined(CONFIG_SERIAL_PCI_BDF) #elif defined(CONFIG_SERIAL_PCI_BDF)
static struct console_uart uart = { static struct console_uart uart = {
.enabled = true, .enabled = true,
.type = PCI, .type = PCI,
.bdf.value = CONFIG_SERIAL_PCI_BDF,
.reg_width = 4, .reg_width = 4,
}; };
static char pci_bdf_info[MAX_BDF_LEN + 1U] = CONFIG_SERIAL_PCI_BDF;
#elif defined(CONFIG_SERIAL_MMIO_BASE) #elif defined(CONFIG_SERIAL_MMIO_BASE)
static struct console_uart uart = { static struct console_uart uart = {
.enabled = true, .enabled = true,
@ -51,38 +51,9 @@ static struct console_uart uart = {
.mmio_base_vaddr = (void *)CONFIG_SERIAL_MMIO_BASE, .mmio_base_vaddr = (void *)CONFIG_SERIAL_MMIO_BASE,
.reg_width = 1, .reg_width = 1,
}; };
static char pci_bdf_info[MAX_BDF_LEN + 1U];
#endif #endif
typedef uint32_t uart_reg_t; typedef uint32_t uart_reg_t;
static union pci_bdf serial_pci_bdf;
/* PCI BDF must follow format: bus:dev.func, for example 0:18.2 */
static uint16_t get_pci_bdf_value(char *bdf)
{
char *pos;
char *start = bdf;
char dst[3][4];
uint64_t value= 0UL;
pos = strchr(start, ':');
if (pos != NULL) {
strncpy_s(dst[0], 3, start, pos -start);
start = pos + 1;
pos = strchr(start, '.');
if (pos != NULL) {
strncpy_s(dst[1], 3, start, pos -start);
start = pos + 1;
strncpy_s(dst[2], 2, start, 1);
value= (strtoul_hex(dst[0]) << 8) | (strtoul_hex(dst[1]) << 3) | strtoul_hex(dst[2]);
}
}
return (uint16_t)value;
}
/** /**
* @pre uart->enabled == true * @pre uart->enabled == true
@ -162,9 +133,8 @@ void uart16550_init(bool early_boot)
/* if configure serial PCI BDF, get its base MMIO address */ /* if configure serial PCI BDF, get its base MMIO address */
if (uart.type == PCI) { if (uart.type == PCI) {
serial_pci_bdf.value = get_pci_bdf_value(pci_bdf_info);
uart.mmio_base_vaddr = uart.mmio_base_vaddr =
hpa2hva_early(pci_pdev_read_cfg(serial_pci_bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE); hpa2hva_early(pci_pdev_read_cfg(uart.bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE);
} }
spinlock_init(&uart.rx_lock); spinlock_init(&uart.rx_lock);
spinlock_init(&uart.tx_lock); spinlock_init(&uart.tx_lock);
@ -245,19 +215,18 @@ size_t uart16550_puts(const char *buf, uint32_t len)
return len; return len;
} }
void uart16550_set_property(bool enabled, enum serial_dev_type uart_type, uint64_t base_addr) void uart16550_set_property(bool enabled, enum serial_dev_type uart_type, uint64_t data)
{ {
uart.enabled = enabled; uart.enabled = enabled;
uart.type = uart_type; uart.type = uart_type;
if (uart_type == PIO) { if (uart_type == PIO) {
uart.port_address = base_addr; uart.port_address = data;
} else if (uart_type == PCI) { } else if (uart_type == PCI) {
const char *bdf = (const char *)base_addr; uart.bdf.value = data;
strncpy_s(pci_bdf_info, MAX_BDF_LEN + 1U, bdf, MAX_BDF_LEN);
uart.reg_width = 4; uart.reg_width = 4;
} else if (uart_type == MMIO) { } else if (uart_type == MMIO) {
uart.mmio_base_vaddr = (void *)base_addr; uart.mmio_base_vaddr = (void *)data;
uart.reg_width = 1; uart.reg_width = 1;
} }
} }
@ -267,7 +236,7 @@ bool is_pci_dbg_uart(union pci_bdf bdf_value)
bool ret = false; bool ret = false;
if (uart.enabled && (uart.type == PCI)) { if (uart.enabled && (uart.type == PCI)) {
if (bdf_value.value == serial_pci_bdf.value) { if (bdf_value.value == uart.bdf.value) {
ret = true; ret = true;
} }
} }