misc: mods: CERT-C L2 fixes

Bug 3745813

Change-Id: If58b0739ca7bca5373e400d0a9468ac4e5e2970a
Signed-off-by: Chris Dragan <kdragan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2797153
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Chris Dragan
2022-10-24 03:03:38 -07:00
committed by Laxman Dewangan
parent 83d81ef365
commit 53daab8b1f
2 changed files with 122 additions and 45 deletions

View File

@@ -166,8 +166,11 @@ static void irq_reg_write(const struct irq_mask_info *m,
{ {
if (m->mask_type == MODS_MASK_TYPE_IRQ_DISABLE64) if (m->mask_type == MODS_MASK_TYPE_IRQ_DISABLE64)
writeq(value, reg); writeq(value, reg);
else else {
writel((u32)value, reg); const u32 val32 = (value > ~0U) ? 0 : value;
writel(val32, reg);
}
} }
static u64 read_irq_state(const struct irq_mask_info *m) static u64 read_irq_state(const struct irq_mask_info *m)
@@ -331,6 +334,9 @@ static irqreturn_t mods_irq_handle(int irq, void *data)
struct dev_irq_map *t = (struct dev_irq_map *)data; struct dev_irq_map *t = (struct dev_irq_map *)data;
int serviced = false; int serviced = false;
if (irq < 0)
return IRQ_RETVAL(false);
if (unlikely(!t)) if (unlikely(!t))
mods_error_printk("received irq %d, but no context for it\n", mods_error_printk("received irq %d, but no context for it\n",
irq); irq);
@@ -562,9 +568,14 @@ static int add_irq_map(struct mods_client *client,
else if ((irq_type == MODS_IRQ_TYPE_INT) || else if ((irq_type == MODS_IRQ_TYPE_INT) ||
(irq_type == MODS_IRQ_TYPE_MSI) || (irq_type == MODS_IRQ_TYPE_MSI) ||
(irq_type == MODS_IRQ_TYPE_MSIX)) { (irq_type == MODS_IRQ_TYPE_MSIX)) {
int dom = dev ? pci_domain_nr(dev->bus) : 0;
if (dom < 0)
dom = 0;
cl_debug(DEBUG_ISR, cl_debug(DEBUG_ISR,
"dev %04x:%02x:%02x.%x registered %s IRQ 0x%x\n", "dev %04x:%02x:%02x.%x registered %s IRQ 0x%x\n",
dev ? pci_domain_nr(dev->bus) : 0U, dom,
dev ? dev->bus->number : 0U, dev ? dev->bus->number : 0U,
dev ? PCI_SLOT(dev->devfn) : 0U, dev ? PCI_SLOT(dev->devfn) : 0U,
dev ? PCI_FUNC(dev->devfn) : 0U, dev ? PCI_FUNC(dev->devfn) : 0U,
@@ -659,7 +670,7 @@ void mods_cleanup_irq(void)
LOG_ENT(); LOG_ENT();
for (i = 0; i < MODS_MAX_CLIENTS; i++) { for (i = 0; i < MODS_MAX_CLIENTS; i++) {
if (mp.client_flags & (1 << i)) if (mp.client_flags & (1U << i))
mods_free_client(i + 1); mods_free_client(i + 1);
} }
LOG_EXT(); LOG_EXT();
@@ -668,7 +679,7 @@ void mods_cleanup_irq(void)
POLL_TYPE mods_irq_event_check(u8 client_id) POLL_TYPE mods_irq_event_check(u8 client_id)
{ {
struct irq_q_info *q = &client_from_id(client_id)->irq_queue; struct irq_q_info *q = &client_from_id(client_id)->irq_queue;
unsigned int pos = (1 << (client_id - 1)); unsigned int pos = (1U << (client_id - 1));
if (!(mp.client_flags & pos)) if (!(mp.client_flags & pos))
return POLLERR; /* irq has quit */ return POLLERR; /* irq has quit */
@@ -681,8 +692,8 @@ POLL_TYPE mods_irq_event_check(u8 client_id)
struct mods_client *mods_alloc_client(void) struct mods_client *mods_alloc_client(void)
{ {
u8 idx; unsigned int idx;
u8 max_clients = 1; unsigned int max_clients = 1;
LOG_ENT(); LOG_ENT();
@@ -691,7 +702,7 @@ struct mods_client *mods_alloc_client(void)
max_clients = MODS_MAX_CLIENTS; max_clients = MODS_MAX_CLIENTS;
for (idx = 1; idx <= max_clients; idx++) { for (idx = 1; idx <= max_clients; idx++) {
if (!test_and_set_bit(idx - 1, &mp.client_flags)) { if (!test_and_set_bit(idx - 1U, &mp.client_flags)) {
struct mods_client *client = client_from_id(idx); struct mods_client *client = client_from_id(idx);
memset(client, 0, sizeof(*client)); memset(client, 0, sizeof(*client));
@@ -841,7 +852,7 @@ void mods_free_client(u8 client_id)
memset(client, 0, sizeof(*client)); memset(client, 0, sizeof(*client));
/* Indicate the client_id is free */ /* Indicate the client_id is free */
clear_bit(client_id - 1, &mp.client_flags); clear_bit((unsigned int)client_id - 1U, &mp.client_flags);
cl_debug(DEBUG_IOCTL, "closed client\n"); cl_debug(DEBUG_IOCTL, "closed client\n");
LOG_EXT(); LOG_EXT();
@@ -1287,26 +1298,39 @@ int esc_mods_register_irq_2(struct mods_client *client,
struct MODS_REGISTER_IRQ_2 *p) struct MODS_REGISTER_IRQ_2 *p)
{ {
struct MODS_REGISTER_IRQ_4 irq_data = { {0} }; struct MODS_REGISTER_IRQ_4 irq_data = { {0} };
#ifdef CONFIG_PCI
struct pci_dev *dev;
int err;
resource_size_t size;
#endif
irq_data.dev = p->dev; irq_data.dev = p->dev;
irq_data.irq_count = 1; irq_data.irq_count = 1;
irq_data.irq_flags = p->type; irq_data.irq_flags = p->type;
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
{
/* Get the PCI device structure */ /* Get the PCI device structure */
struct pci_dev *dev;
int err;
err = mods_find_pci_dev(client, &p->dev, &dev); err = mods_find_pci_dev(client, &p->dev, &dev);
if (unlikely(err)) if (unlikely(err))
return err; return err;
irq_data.aperture_addr = pci_resource_start(dev, 0); irq_data.aperture_addr = pci_resource_start(dev, 0);
irq_data.aperture_size = pci_resource_len(dev, 0);
size = pci_resource_len(dev, 0);
pci_dev_put(dev); pci_dev_put(dev);
if (size > ~0U) {
cl_error("BAR0 size of device %04x:%02x:%02x.%x is %llx and exceeds 32 bits\n",
p->dev.domain,
p->dev.bus,
p->dev.device,
p->dev.function,
(unsigned long long)size);
return -EINVAL;
} }
irq_data.aperture_size = (unsigned int)size;
#endif #endif
return esc_mods_register_irq_4(client, &irq_data); return esc_mods_register_irq_4(client, &irq_data);
@@ -1356,6 +1380,7 @@ int esc_mods_query_irq_3(struct mods_client *client,
struct MODS_QUERY_IRQ_3 *p) struct MODS_QUERY_IRQ_3 *p)
{ {
struct irq_q_info *q = NULL; struct irq_q_info *q = NULL;
int err = OK;
unsigned int i = 0; unsigned int i = 0;
unsigned long flags = 0; unsigned long flags = 0;
unsigned int cur_time = get_cur_time(); unsigned int cur_time = get_cur_time();
@@ -1378,11 +1403,24 @@ int esc_mods_query_irq_3(struct mods_client *client,
struct pci_dev *dev = q->data[index].dev; struct pci_dev *dev = q->data[index].dev;
if (dev) { if (dev) {
p->irq_list[i].dev.domain = pci_domain_nr(dev->bus); const int dom = pci_domain_nr(dev->bus);
if (dom < 0 || dom > 0xFFFF) {
cl_error("unsupported domain %d\n", dom);
err = -EINVAL;
goto error;
}
p->irq_list[i].dev.domain = dom;
p->irq_list[i].dev.bus = dev->bus->number; p->irq_list[i].dev.bus = dev->bus->number;
p->irq_list[i].dev.device = PCI_SLOT(dev->devfn); p->irq_list[i].dev.device = PCI_SLOT(dev->devfn);
p->irq_list[i].dev.function = PCI_FUNC(dev->devfn); p->irq_list[i].dev.function = PCI_FUNC(dev->devfn);
} else { } else {
if (q->data[index].irq > 0xFFFFU) {
cl_error("unsupported IRQ %u\n",
q->data[index].irq);
err = -EINVAL;
goto error;
}
p->irq_list[i].dev.domain = 0; p->irq_list[i].dev.domain = 0;
p->irq_list[i].dev.bus = q->data[index].irq; p->irq_list[i].dev.bus = q->data[index].irq;
p->irq_list[i].dev.device = 0xFFU; p->irq_list[i].dev.device = 0xFFU;
@@ -1415,11 +1453,12 @@ int esc_mods_query_irq_3(struct mods_client *client,
if (q->head != q->tail) if (q->head != q->tail)
p->more = 1; p->more = 1;
error:
/* Unlock IRQ queue */ /* Unlock IRQ queue */
spin_unlock_irqrestore(&client->irq_lock, flags); spin_unlock_irqrestore(&client->irq_lock, flags);
LOG_EXT(); LOG_EXT();
return OK; return err;
} }
int esc_mods_query_irq_2(struct mods_client *client, int esc_mods_query_irq_2(struct mods_client *client,
@@ -1451,11 +1490,22 @@ int esc_mods_query_irq(struct mods_client *client,
return retval; return retval;
for (i = 0; i < MODS_MAX_IRQS; i++) { for (i = 0; i < MODS_MAX_IRQS; i++) {
p->irq_list[i].dev.bus = query_irq.irq_list[i].dev.bus; struct mods_irq_3 *entry = &query_irq.irq_list[i];
p->irq_list[i].dev.device = query_irq.irq_list[i].dev.device;
p->irq_list[i].dev.function if (entry->dev.device > 0xFFU) {
= query_irq.irq_list[i].dev.function; cl_error("unsupported device %02x\n",
p->irq_list[i].delay = query_irq.irq_list[i].delay; entry->dev.device);
return -EINVAL;
}
if (entry->dev.function > 0xFFU) {
cl_error("unsupported function %02x\n",
entry->dev.function);
return -EINVAL;
}
p->irq_list[i].dev.bus = entry->dev.bus;
p->irq_list[i].dev.device = entry->dev.device;
p->irq_list[i].dev.function = entry->dev.function;
p->irq_list[i].delay = entry->delay;
} }
p->more = query_irq.more; p->more = query_irq.more;
return OK; return OK;
@@ -1548,14 +1598,24 @@ int esc_mods_map_irq(struct mods_client *client,
} }
} }
if (p->index > 0x7FFFFFFFU) {
cl_error("unsupported index %u\n", p->index);
err = -EINVAL;
goto error;
}
p->irq = irq_of_parse_and_map(np, p->index); p->irq = irq_of_parse_and_map(np, p->index);
err = of_irq_parse_one(np, p->index, &oirq); err = of_irq_parse_one(np, p->index, &oirq);
if (err) { if (err) {
cl_error("could not parse IRQ\n"); cl_error("could not parse IRQ\n");
goto error; goto error;
} }
if ((int)oirq.args[1] < 0) {
cl_error("unsupported IRQ %d\n", (int)oirq.args[1]);
err = -EINVAL;
goto error;
}
hwirq = oirq.args[1]; hwirq = (int)oirq.args[1];
/* Get the platform device handle */ /* Get the platform device handle */
pdev = of_find_device_by_node(np); pdev = of_find_device_by_node(np);
@@ -1567,12 +1627,13 @@ int esc_mods_map_irq(struct mods_client *client,
struct resource *res_tke = struct resource *res_tke =
platform_get_resource(pdev, IORESOURCE_MEM, 2); platform_get_resource(pdev, IORESOURCE_MEM, 2);
void __iomem *wdt_tke = NULL; void __iomem *wdt_tke = NULL;
int wdt_index; unsigned int wdt_index = 0;
if (res_tke && res_src) { if (res_tke && res_src) {
wdt_tke = devm_ioremap(&pdev->dev, res_tke->start, wdt_tke = devm_ioremap(&pdev->dev, res_tke->start,
resource_size(res_tke)); resource_size(res_tke));
wdt_index = ((res_src->start >> 16) & 0xF) - 0xc; wdt_index = (unsigned int)
(((res_src->start >> 16) & 0xFU) - 0xCU);
} }
if (wdt_tke) { if (wdt_tke) {

View File

@@ -227,6 +227,12 @@ static int esc_mods_set_num_vf(struct mods_client *client,
LOG_ENT(); LOG_ENT();
if (p->numvfs > 0xFFFFU) {
cl_error("invalid input numfs %u\n", p->numvfs);
err = -EINVAL;
goto error;
}
/* Get the PCI device structure for the specified device from kernel */ /* Get the PCI device structure for the specified device from kernel */
err = mods_find_pci_dev(client, &p->dev, &dev); err = mods_find_pci_dev(client, &p->dev, &dev);
if (unlikely(err)) { if (unlikely(err)) {
@@ -236,8 +242,7 @@ static int esc_mods_set_num_vf(struct mods_client *client,
p->dev.bus, p->dev.bus,
p->dev.device, p->dev.device,
p->dev.function); p->dev.function);
LOG_EXT(); goto error;
return err;
} }
dpriv = pci_get_drvdata(dev); dpriv = pci_get_drvdata(dev);
@@ -263,7 +268,7 @@ static int esc_mods_set_num_vf(struct mods_client *client,
goto error; goto error;
} }
err = mods_pci_sriov_configure(dev, p->numvfs); err = mods_pci_sriov_configure(dev, (u16)p->numvfs);
error: error:
pci_dev_put(dev); pci_dev_put(dev);
@@ -280,6 +285,12 @@ static int esc_mods_set_total_vf(struct mods_client *client,
LOG_ENT(); LOG_ENT();
if (p->numvfs > 0xFFFFU) {
cl_error("invalid input numfs %u\n", p->numvfs);
err = -EINVAL;
goto error;
}
/* Get the PCI device structure for the specified device from kernel */ /* Get the PCI device structure for the specified device from kernel */
err = mods_find_pci_dev(client, &p->dev, &dev); err = mods_find_pci_dev(client, &p->dev, &dev);
if (unlikely(err)) { if (unlikely(err)) {
@@ -289,8 +300,7 @@ static int esc_mods_set_total_vf(struct mods_client *client,
p->dev.bus, p->dev.bus,
p->dev.device, p->dev.device,
p->dev.function); p->dev.function);
LOG_EXT(); goto error;
return -EINVAL;
} }
dpriv = pci_get_drvdata(dev); dpriv = pci_get_drvdata(dev);
@@ -316,7 +326,7 @@ static int esc_mods_set_total_vf(struct mods_client *client,
goto error; goto error;
} }
err = pci_sriov_set_totalvfs(dev, p->numvfs); err = pci_sriov_set_totalvfs(dev, (u16)p->numvfs);
if (unlikely(err)) { if (unlikely(err)) {
cl_error( cl_error(
@@ -1017,12 +1027,12 @@ static int mods_krnl_close(struct inode *ip, struct file *fp)
mods_disable_all_devices(client); mods_disable_all_devices(client);
{ {
unsigned long num_allocs = atomic_read(&client->num_allocs); const int num_allocs = atomic_read(&client->num_allocs);
unsigned long num_pages = atomic_read(&client->num_pages); const int num_pages = atomic_read(&client->num_pages);
if (num_allocs || num_pages) { if (num_allocs || num_pages) {
cl_error( cl_error(
"not all allocations have been freed, allocs=%lu, pages=%lu\n", "not all allocations have been freed, allocs=%d, pages=%d\n",
num_allocs, num_pages); num_allocs, num_pages);
if (!final_err) if (!final_err)
final_err = -ENOMEM; final_err = -ENOMEM;
@@ -1180,9 +1190,9 @@ static int map_system_mem(struct mods_client *client,
map_size = (unsigned int)size_to_map; map_size = (unsigned int)size_to_map;
cl_debug(DEBUG_MEM_DETAILED, cl_debug(DEBUG_MEM_DETAILED,
"remap va 0x%lx pfn 0x%x size 0x%x pages %u\n", "remap va 0x%lx pfn 0x%lx size 0x%x pages %u\n",
map_va, map_va,
(unsigned int)(map_pa >> PAGE_SHIFT), (unsigned long)(map_pa >> PAGE_SHIFT),
map_size, map_size,
map_size >> PAGE_SHIFT); map_size >> PAGE_SHIFT);
@@ -1596,7 +1606,7 @@ struct mods_file_work {
const char *path; const char *path;
const char *data; const char *data;
u32 data_size; u32 data_size;
int err; ssize_t err;
}; };
static void sysfs_write_task(struct work_struct *w) static void sysfs_write_task(struct work_struct *w)
@@ -1678,7 +1688,7 @@ static int run_write_task(struct mods_client *client,
cl_error("failed to write %.*s to %s\n", cl_error("failed to write %.*s to %s\n",
task->data_size, task->data, task->path); task->data_size, task->data, task->path);
return (task->err > 0) ? 0 : task->err; return (task->err > 0) ? 0 : (int)task->err;
} }
static int esc_mods_write_sysfs_node(struct mods_client *client, static int esc_mods_write_sysfs_node(struct mods_client *client,
@@ -1778,12 +1788,18 @@ static int esc_mods_write_msr(struct mods_client *client, struct MODS_MSR *p)
static int esc_mods_get_driver_stats(struct mods_client *client, static int esc_mods_get_driver_stats(struct mods_client *client,
struct MODS_GET_DRIVER_STATS *p) struct MODS_GET_DRIVER_STATS *p)
{ {
int num_allocs;
int num_pages;
LOG_ENT(); LOG_ENT();
num_allocs = atomic_read(&client->num_allocs);
num_pages = atomic_read(&client->num_pages);
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
p->version = MODS_DRIVER_STATS_VERSION; p->version = MODS_DRIVER_STATS_VERSION;
p->num_allocs = atomic_read(&client->num_allocs); p->num_allocs = (num_allocs < 0) ? ~0U : num_allocs;
p->num_pages = atomic_read(&client->num_pages); p->num_pages = (num_pages < 0) ? ~0U : num_pages;
LOG_EXT(); LOG_EXT();
return 0; return 0;