Commit 9c97ceca authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'misc-habanalabs-fixes-2020-08-22' of...

Merge tag 'misc-habanalabs-fixes-2020-08-22' of git://people.freedesktop.org/~gabbayo/linux into char-misc-linus

Oded writes:

This tag contains the following bug fixes for 5.9-rc2/3:

- Correct cleanup of PCI bar mapping in case of failure during
  initialization.

- Several security fixes:
  - Validating user addresses before mapping them
  - Validating packet id (from user) before using it as index for array.
  - Validating F/W file size before coping it.
  - Prevent possible overflow when validating address from user in
    profiler.
  - Validate queue index (from user) before using it as index for array.
  - Check for correct vmalloc return code

- Fix memory corruption in debugfs entry

- Fix a loop in gaudi_extract_ecc_info()

- Fix the set clock gating function in gaudi code

- Set maximum power to F/W according to the card type

- Cix incorrect check on failed workqueue create

- Correctly report error when configuring the PCI controller

* tag 'misc-habanalabs-fixes-2020-08-22' of git://people.freedesktop.org/~gabbayo/linux:
  habanalabs: correctly report inbound pci region cfg error
  habanalabs: check correct vmalloc return code
  habanalabs: validate FW file size
  habanalabs: fix incorrect check on failed workqueue create
  habanalabs: set max power according to card type
  habanalabs: proper handling of alloc size in coresight
  habanalabs: set clock gating according to mask
  habanalabs: verify user input in cs_ioctl_signal_wait
  habanalabs: Fix a loop in gaudi_extract_ecc_info()
  habanalabs: Fix memory corruption in debugfs
  habanalabs: validate packet id during CB parse
  habanalabs: Validate user address before mapping
  habanalabs: unmap PCI bars upon iATU failure
parents 51072c0f 5aba3688
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/genalloc.h> #include <linux/genalloc.h>
static void cb_fini(struct hl_device *hdev, struct hl_cb *cb) static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
...@@ -300,7 +301,7 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) ...@@ -300,7 +301,7 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
struct hl_device *hdev = hpriv->hdev; struct hl_device *hdev = hpriv->hdev;
struct hl_cb *cb; struct hl_cb *cb;
phys_addr_t address; phys_addr_t address;
u32 handle; u32 handle, user_cb_size;
int rc; int rc;
handle = vma->vm_pgoff; handle = vma->vm_pgoff;
...@@ -314,7 +315,8 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) ...@@ -314,7 +315,8 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
} }
/* Validation check */ /* Validation check */
if ((vma->vm_end - vma->vm_start) != ALIGN(cb->size, PAGE_SIZE)) { user_cb_size = vma->vm_end - vma->vm_start;
if (user_cb_size != ALIGN(cb->size, PAGE_SIZE)) {
dev_err(hdev->dev, dev_err(hdev->dev,
"CB mmap failed, mmap size 0x%lx != 0x%x cb size\n", "CB mmap failed, mmap size 0x%lx != 0x%x cb size\n",
vma->vm_end - vma->vm_start, cb->size); vma->vm_end - vma->vm_start, cb->size);
...@@ -322,6 +324,16 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) ...@@ -322,6 +324,16 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
goto put_cb; goto put_cb;
} }
if (!access_ok((void __user *) (uintptr_t) vma->vm_start,
user_cb_size)) {
dev_err(hdev->dev,
"user pointer is invalid - 0x%lx\n",
vma->vm_start);
rc = -EINVAL;
goto put_cb;
}
spin_lock(&cb->lock); spin_lock(&cb->lock);
if (cb->mmap) { if (cb->mmap) {
......
...@@ -808,6 +808,14 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type, ...@@ -808,6 +808,14 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,
/* currently it is guaranteed to have only one chunk */ /* currently it is guaranteed to have only one chunk */
chunk = &cs_chunk_array[0]; chunk = &cs_chunk_array[0];
if (chunk->queue_index >= hdev->asic_prop.max_queues) {
dev_err(hdev->dev, "Queue index %d is invalid\n",
chunk->queue_index);
rc = -EINVAL;
goto free_cs_chunk_array;
}
q_idx = chunk->queue_index; q_idx = chunk->queue_index;
hw_queue_prop = &hdev->asic_prop.hw_queues_props[q_idx]; hw_queue_prop = &hdev->asic_prop.hw_queues_props[q_idx];
q_type = hw_queue_prop->type; q_type = hw_queue_prop->type;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static struct dentry *hl_debug_root; static struct dentry *hl_debug_root;
static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr, static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
u8 i2c_reg, u32 *val) u8 i2c_reg, long *val)
{ {
struct armcp_packet pkt; struct armcp_packet pkt;
int rc; int rc;
...@@ -36,7 +36,7 @@ static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr, ...@@ -36,7 +36,7 @@ static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
pkt.i2c_reg = i2c_reg; pkt.i2c_reg = i2c_reg;
rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
0, (long *) val); 0, val);
if (rc) if (rc)
dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc); dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);
...@@ -827,7 +827,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf, ...@@ -827,7 +827,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
struct hl_dbg_device_entry *entry = file_inode(f)->i_private; struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
struct hl_device *hdev = entry->hdev; struct hl_device *hdev = entry->hdev;
char tmp_buf[32]; char tmp_buf[32];
u32 val; long val;
ssize_t rc; ssize_t rc;
if (*ppos) if (*ppos)
...@@ -842,7 +842,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf, ...@@ -842,7 +842,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
return rc; return rc;
} }
sprintf(tmp_buf, "0x%02x\n", val); sprintf(tmp_buf, "0x%02lx\n", val);
rc = simple_read_from_buffer(buf, count, ppos, tmp_buf, rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
strlen(tmp_buf)); strlen(tmp_buf));
......
...@@ -288,7 +288,7 @@ static int device_early_init(struct hl_device *hdev) ...@@ -288,7 +288,7 @@ static int device_early_init(struct hl_device *hdev)
for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) { for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) {
snprintf(workq_name, 32, "hl-free-jobs-%u", i); snprintf(workq_name, 32, "hl-free-jobs-%u", i);
hdev->cq_wq[i] = create_singlethread_workqueue(workq_name); hdev->cq_wq[i] = create_singlethread_workqueue(workq_name);
if (hdev->cq_wq == NULL) { if (hdev->cq_wq[i] == NULL) {
dev_err(hdev->dev, "Failed to allocate CQ workqueue\n"); dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
rc = -ENOMEM; rc = -ENOMEM;
goto free_cq_wq; goto free_cq_wq;
...@@ -1069,7 +1069,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset, ...@@ -1069,7 +1069,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
goto out_err; goto out_err;
} }
hl_set_max_power(hdev, hdev->max_power); hl_set_max_power(hdev);
} else { } else {
rc = hdev->asic_funcs->soft_reset_late_init(hdev); rc = hdev->asic_funcs->soft_reset_late_init(hdev);
if (rc) { if (rc) {
...@@ -1318,6 +1318,11 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) ...@@ -1318,6 +1318,11 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
goto out_disabled; goto out_disabled;
} }
/* Need to call this again because the max power might change,
* depending on card type for certain ASICs
*/
hl_set_max_power(hdev);
/* /*
* hl_hwmon_init() must be called after device_late_init(), because only * hl_hwmon_init() must be called after device_late_init(), because only
* there we get the information from the device about which * there we get the information from the device about which
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/io-64-nonatomic-lo-hi.h> #include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/slab.h> #include <linux/slab.h>
#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */
/** /**
* hl_fw_load_fw_to_device() - Load F/W code to device's memory. * hl_fw_load_fw_to_device() - Load F/W code to device's memory.
* *
...@@ -48,6 +49,14 @@ int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, ...@@ -48,6 +49,14 @@ int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name,
dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size); dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
if (fw_size > FW_FILE_MAX_SIZE) {
dev_err(hdev->dev,
"FW file size %zu exceeds maximum of %u bytes\n",
fw_size, FW_FILE_MAX_SIZE);
rc = -EINVAL;
goto out;
}
fw_data = (const u64 *) fw->data; fw_data = (const u64 *) fw->data;
memcpy_toio(dst, fw_data, fw_size); memcpy_toio(dst, fw_data, fw_size);
......
...@@ -1462,6 +1462,8 @@ struct hl_device_idle_busy_ts { ...@@ -1462,6 +1462,8 @@ struct hl_device_idle_busy_ts {
* details. * details.
* @in_reset: is device in reset flow. * @in_reset: is device in reset flow.
* @curr_pll_profile: current PLL profile. * @curr_pll_profile: current PLL profile.
* @card_type: Various ASICs have several card types. This indicates the card
* type of the current device.
* @cs_active_cnt: number of active command submissions on this device (active * @cs_active_cnt: number of active command submissions on this device (active
* means already in H/W queues) * means already in H/W queues)
* @major: habanalabs kernel driver major. * @major: habanalabs kernel driver major.
...@@ -1566,6 +1568,7 @@ struct hl_device { ...@@ -1566,6 +1568,7 @@ struct hl_device {
u64 clock_gating_mask; u64 clock_gating_mask;
atomic_t in_reset; atomic_t in_reset;
enum hl_pll_frequency curr_pll_profile; enum hl_pll_frequency curr_pll_profile;
enum armcp_card_types card_type;
int cs_active_cnt; int cs_active_cnt;
u32 major; u32 major;
u32 high_pll; u32 high_pll;
...@@ -1651,7 +1654,7 @@ struct hl_ioctl_desc { ...@@ -1651,7 +1654,7 @@ struct hl_ioctl_desc {
* *
* Return: true if the area is inside the valid range, false otherwise. * Return: true if the area is inside the valid range, false otherwise.
*/ */
static inline bool hl_mem_area_inside_range(u64 address, u32 size, static inline bool hl_mem_area_inside_range(u64 address, u64 size,
u64 range_start_address, u64 range_end_address) u64 range_start_address, u64 range_end_address)
{ {
u64 end_address = address + size; u64 end_address = address + size;
...@@ -1858,7 +1861,7 @@ int hl_get_pwm_info(struct hl_device *hdev, ...@@ -1858,7 +1861,7 @@ int hl_get_pwm_info(struct hl_device *hdev,
void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr, void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
long value); long value);
u64 hl_get_max_power(struct hl_device *hdev); u64 hl_get_max_power(struct hl_device *hdev);
void hl_set_max_power(struct hl_device *hdev, u64 value); void hl_set_max_power(struct hl_device *hdev);
int hl_set_voltage(struct hl_device *hdev, int hl_set_voltage(struct hl_device *hdev,
int sensor_index, u32 attr, long value); int sensor_index, u32 attr, long value);
int hl_set_current(struct hl_device *hdev, int hl_set_current(struct hl_device *hdev,
......
...@@ -66,6 +66,11 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args, ...@@ -66,6 +66,11 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift; num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift;
total_size = num_pgs << page_shift; total_size = num_pgs << page_shift;
if (!total_size) {
dev_err(hdev->dev, "Cannot allocate 0 bytes\n");
return -EINVAL;
}
contiguous = args->flags & HL_MEM_CONTIGUOUS; contiguous = args->flags & HL_MEM_CONTIGUOUS;
if (contiguous) { if (contiguous) {
...@@ -93,7 +98,7 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args, ...@@ -93,7 +98,7 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
phys_pg_pack->contiguous = contiguous; phys_pg_pack->contiguous = contiguous;
phys_pg_pack->pages = kvmalloc_array(num_pgs, sizeof(u64), GFP_KERNEL); phys_pg_pack->pages = kvmalloc_array(num_pgs, sizeof(u64), GFP_KERNEL);
if (!phys_pg_pack->pages) { if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
rc = -ENOMEM; rc = -ENOMEM;
goto pages_arr_err; goto pages_arr_err;
} }
...@@ -683,7 +688,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx, ...@@ -683,7 +688,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
phys_pg_pack->pages = kvmalloc_array(total_npages, sizeof(u64), phys_pg_pack->pages = kvmalloc_array(total_npages, sizeof(u64),
GFP_KERNEL); GFP_KERNEL);
if (!phys_pg_pack->pages) { if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
rc = -ENOMEM; rc = -ENOMEM;
goto page_pack_arr_mem_err; goto page_pack_arr_mem_err;
} }
......
...@@ -450,7 +450,7 @@ int hl_mmu_init(struct hl_device *hdev) ...@@ -450,7 +450,7 @@ int hl_mmu_init(struct hl_device *hdev)
hdev->mmu_shadow_hop0 = kvmalloc_array(prop->max_asid, hdev->mmu_shadow_hop0 = kvmalloc_array(prop->max_asid,
prop->mmu_hop_table_size, prop->mmu_hop_table_size,
GFP_KERNEL | __GFP_ZERO); GFP_KERNEL | __GFP_ZERO);
if (!hdev->mmu_shadow_hop0) { if (ZERO_OR_NULL_PTR(hdev->mmu_shadow_hop0)) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_pool_add; goto err_pool_add;
} }
......
...@@ -227,7 +227,7 @@ int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region, ...@@ -227,7 +227,7 @@ int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
} }
/* Point to the specified address */ /* Point to the specified address */
rc = hl_pci_iatu_write(hdev, offset + 0x14, rc |= hl_pci_iatu_write(hdev, offset + 0x14,
lower_32_bits(pci_region->addr)); lower_32_bits(pci_region->addr));
rc |= hl_pci_iatu_write(hdev, offset + 0x18, rc |= hl_pci_iatu_write(hdev, offset + 0x18,
upper_32_bits(pci_region->addr)); upper_32_bits(pci_region->addr));
...@@ -369,15 +369,17 @@ int hl_pci_init(struct hl_device *hdev) ...@@ -369,15 +369,17 @@ int hl_pci_init(struct hl_device *hdev)
rc = hdev->asic_funcs->init_iatu(hdev); rc = hdev->asic_funcs->init_iatu(hdev);
if (rc) { if (rc) {
dev_err(hdev->dev, "Failed to initialize iATU\n"); dev_err(hdev->dev, "Failed to initialize iATU\n");
goto disable_device; goto unmap_pci_bars;
} }
rc = hl_pci_set_dma_mask(hdev); rc = hl_pci_set_dma_mask(hdev);
if (rc) if (rc)
goto disable_device; goto unmap_pci_bars;
return 0; return 0;
unmap_pci_bars:
hl_pci_bars_unmap(hdev);
disable_device: disable_device:
pci_clear_master(pdev); pci_clear_master(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
......
...@@ -81,7 +81,7 @@ u64 hl_get_max_power(struct hl_device *hdev) ...@@ -81,7 +81,7 @@ u64 hl_get_max_power(struct hl_device *hdev)
return result; return result;
} }
void hl_set_max_power(struct hl_device *hdev, u64 value) void hl_set_max_power(struct hl_device *hdev)
{ {
struct armcp_packet pkt; struct armcp_packet pkt;
int rc; int rc;
...@@ -90,7 +90,7 @@ void hl_set_max_power(struct hl_device *hdev, u64 value) ...@@ -90,7 +90,7 @@ void hl_set_max_power(struct hl_device *hdev, u64 value)
pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET << pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
ARMCP_PKT_CTL_OPCODE_SHIFT); ARMCP_PKT_CTL_OPCODE_SHIFT);
pkt.value = cpu_to_le64(value); pkt.value = cpu_to_le64(hdev->max_power);
rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
0, NULL); 0, NULL);
...@@ -316,7 +316,7 @@ static ssize_t max_power_store(struct device *dev, ...@@ -316,7 +316,7 @@ static ssize_t max_power_store(struct device *dev,
} }
hdev->max_power = value; hdev->max_power = value;
hl_set_max_power(hdev, value); hl_set_max_power(hdev);
out: out:
return count; return count;
...@@ -422,6 +422,7 @@ int hl_sysfs_init(struct hl_device *hdev) ...@@ -422,6 +422,7 @@ int hl_sysfs_init(struct hl_device *hdev)
hdev->pm_mng_profile = PM_AUTO; hdev->pm_mng_profile = PM_AUTO;
else else
hdev->pm_mng_profile = PM_MANUAL; hdev->pm_mng_profile = PM_MANUAL;
hdev->max_power = hdev->asic_prop.max_power_default; hdev->max_power = hdev->asic_prop.max_power_default;
hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group); hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
......
...@@ -154,6 +154,29 @@ static const u16 gaudi_packet_sizes[MAX_PACKET_ID] = { ...@@ -154,6 +154,29 @@ static const u16 gaudi_packet_sizes[MAX_PACKET_ID] = {
[PACKET_LOAD_AND_EXE] = sizeof(struct packet_load_and_exe) [PACKET_LOAD_AND_EXE] = sizeof(struct packet_load_and_exe)
}; };
static inline bool validate_packet_id(enum packet_id id)
{
switch (id) {
case PACKET_WREG_32:
case PACKET_WREG_BULK:
case PACKET_MSG_LONG:
case PACKET_MSG_SHORT:
case PACKET_CP_DMA:
case PACKET_REPEAT:
case PACKET_MSG_PROT:
case PACKET_FENCE:
case PACKET_LIN_DMA:
case PACKET_NOP:
case PACKET_STOP:
case PACKET_ARB_POINT:
case PACKET_WAIT:
case PACKET_LOAD_AND_EXE:
return true;
default:
return false;
}
}
static const char * const static const char * const
gaudi_tpc_interrupts_cause[GAUDI_NUM_OF_TPC_INTR_CAUSE] = { gaudi_tpc_interrupts_cause[GAUDI_NUM_OF_TPC_INTR_CAUSE] = {
"tpc_address_exceed_slm", "tpc_address_exceed_slm",
...@@ -433,7 +456,7 @@ static int gaudi_get_fixed_properties(struct hl_device *hdev) ...@@ -433,7 +456,7 @@ static int gaudi_get_fixed_properties(struct hl_device *hdev)
prop->num_of_events = GAUDI_EVENT_SIZE; prop->num_of_events = GAUDI_EVENT_SIZE;
prop->tpc_enabled_mask = TPC_ENABLED_MASK; prop->tpc_enabled_mask = TPC_ENABLED_MASK;
prop->max_power_default = MAX_POWER_DEFAULT; prop->max_power_default = MAX_POWER_DEFAULT_PCI;
prop->cb_pool_cb_cnt = GAUDI_CB_POOL_CB_CNT; prop->cb_pool_cb_cnt = GAUDI_CB_POOL_CB_CNT;
prop->cb_pool_cb_size = GAUDI_CB_POOL_CB_SIZE; prop->cb_pool_cb_size = GAUDI_CB_POOL_CB_SIZE;
...@@ -2485,6 +2508,7 @@ static void gaudi_set_clock_gating(struct hl_device *hdev) ...@@ -2485,6 +2508,7 @@ static void gaudi_set_clock_gating(struct hl_device *hdev)
{ {
struct gaudi_device *gaudi = hdev->asic_specific; struct gaudi_device *gaudi = hdev->asic_specific;
u32 qman_offset; u32 qman_offset;
bool enable;
int i; int i;
/* In case we are during debug session, don't enable the clock gate /* In case we are during debug session, don't enable the clock gate
...@@ -2494,46 +2518,43 @@ static void gaudi_set_clock_gating(struct hl_device *hdev) ...@@ -2494,46 +2518,43 @@ static void gaudi_set_clock_gating(struct hl_device *hdev)
return; return;
for (i = GAUDI_PCI_DMA_1, qman_offset = 0 ; i < GAUDI_HBM_DMA_1 ; i++) { for (i = GAUDI_PCI_DMA_1, qman_offset = 0 ; i < GAUDI_HBM_DMA_1 ; i++) {
if (!(hdev->clock_gating_mask & enable = !!(hdev->clock_gating_mask &
(BIT_ULL(gaudi_dma_assignment[i])))) (BIT_ULL(gaudi_dma_assignment[i])));
continue;
qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET; qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET;
WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset, QMAN_CGM1_PWR_GATE_EN); WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset,
enable ? QMAN_CGM1_PWR_GATE_EN : 0);
WREG32(mmDMA0_QM_CGM_CFG + qman_offset, WREG32(mmDMA0_QM_CGM_CFG + qman_offset,
QMAN_UPPER_CP_CGM_PWR_GATE_EN); enable ? QMAN_UPPER_CP_CGM_PWR_GATE_EN : 0);
} }
for (i = GAUDI_HBM_DMA_1 ; i < GAUDI_DMA_MAX ; i++) { for (i = GAUDI_HBM_DMA_1 ; i < GAUDI_DMA_MAX ; i++) {
if (!(hdev->clock_gating_mask & enable = !!(hdev->clock_gating_mask &
(BIT_ULL(gaudi_dma_assignment[i])))) (BIT_ULL(gaudi_dma_assignment[i])));
continue;
qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET; qman_offset = gaudi_dma_assignment[i] * DMA_QMAN_OFFSET;
WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset, QMAN_CGM1_PWR_GATE_EN); WREG32(mmDMA0_QM_CGM_CFG1 + qman_offset,
enable ? QMAN_CGM1_PWR_GATE_EN : 0);
WREG32(mmDMA0_QM_CGM_CFG + qman_offset, WREG32(mmDMA0_QM_CGM_CFG + qman_offset,
QMAN_COMMON_CP_CGM_PWR_GATE_EN); enable ? QMAN_COMMON_CP_CGM_PWR_GATE_EN : 0);
} }
if (hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_0))) { enable = !!(hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_0)));
WREG32(mmMME0_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN); WREG32(mmMME0_QM_CGM_CFG1, enable ? QMAN_CGM1_PWR_GATE_EN : 0);
WREG32(mmMME0_QM_CGM_CFG, QMAN_COMMON_CP_CGM_PWR_GATE_EN); WREG32(mmMME0_QM_CGM_CFG, enable ? QMAN_COMMON_CP_CGM_PWR_GATE_EN : 0);
}
if (hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_2))) { enable = !!(hdev->clock_gating_mask & (BIT_ULL(GAUDI_ENGINE_ID_MME_2)));
WREG32(mmMME2_QM_CGM_CFG1, QMAN_CGM1_PWR_GATE_EN); WREG32(mmMME2_QM_CGM_CFG1, enable ? QMAN_CGM1_PWR_GATE_EN : 0);
WREG32(mmMME2_QM_CGM_CFG, QMAN_COMMON_CP_CGM_PWR_GATE_EN); WREG32(mmMME2_QM_CGM_CFG, enable ? QMAN_COMMON_CP_CGM_PWR_GATE_EN : 0);
}
for (i = 0, qman_offset = 0 ; i < TPC_NUMBER_OF_ENGINES ; i++) { for (i = 0, qman_offset = 0 ; i < TPC_NUMBER_OF_ENGINES ; i++) {
if (!(hdev->clock_gating_mask & enable = !!(hdev->clock_gating_mask &
(BIT_ULL(GAUDI_ENGINE_ID_TPC_0 + i)))) (BIT_ULL(GAUDI_ENGINE_ID_TPC_0 + i)));
continue;
WREG32(mmTPC0_QM_CGM_CFG1 + qman_offset, WREG32(mmTPC0_QM_CGM_CFG1 + qman_offset,
QMAN_CGM1_PWR_GATE_EN); enable ? QMAN_CGM1_PWR_GATE_EN : 0);
WREG32(mmTPC0_QM_CGM_CFG + qman_offset, WREG32(mmTPC0_QM_CGM_CFG + qman_offset,
QMAN_COMMON_CP_CGM_PWR_GATE_EN); enable ? QMAN_COMMON_CP_CGM_PWR_GATE_EN : 0);
qman_offset += TPC_QMAN_OFFSET; qman_offset += TPC_QMAN_OFFSET;
} }
...@@ -3772,6 +3793,12 @@ static int gaudi_validate_cb(struct hl_device *hdev, ...@@ -3772,6 +3793,12 @@ static int gaudi_validate_cb(struct hl_device *hdev,
PACKET_HEADER_PACKET_ID_MASK) >> PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT); PACKET_HEADER_PACKET_ID_SHIFT);
if (!validate_packet_id(pkt_id)) {
dev_err(hdev->dev, "Invalid packet id %u\n", pkt_id);
rc = -EINVAL;
break;
}
pkt_size = gaudi_packet_sizes[pkt_id]; pkt_size = gaudi_packet_sizes[pkt_id];
cb_parsed_length += pkt_size; cb_parsed_length += pkt_size;
if (cb_parsed_length > parser->user_cb_size) { if (cb_parsed_length > parser->user_cb_size) {
...@@ -3995,6 +4022,12 @@ static int gaudi_patch_cb(struct hl_device *hdev, ...@@ -3995,6 +4022,12 @@ static int gaudi_patch_cb(struct hl_device *hdev,
PACKET_HEADER_PACKET_ID_MASK) >> PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT); PACKET_HEADER_PACKET_ID_SHIFT);
if (!validate_packet_id(pkt_id)) {
dev_err(hdev->dev, "Invalid packet id %u\n", pkt_id);
rc = -EINVAL;
break;
}
pkt_size = gaudi_packet_sizes[pkt_id]; pkt_size = gaudi_packet_sizes[pkt_id];
cb_parsed_length += pkt_size; cb_parsed_length += pkt_size;
if (cb_parsed_length > parser->user_cb_size) { if (cb_parsed_length > parser->user_cb_size) {
...@@ -5215,7 +5248,7 @@ static int gaudi_extract_ecc_info(struct hl_device *hdev, ...@@ -5215,7 +5248,7 @@ static int gaudi_extract_ecc_info(struct hl_device *hdev,
*memory_wrapper_idx = 0xFF; *memory_wrapper_idx = 0xFF;
/* Iterate through memory wrappers, a single bit must be set */ /* Iterate through memory wrappers, a single bit must be set */
for (i = 0 ; i > num_mem_regs ; i++) { for (i = 0 ; i < num_mem_regs ; i++) {
err_addr += i * 4; err_addr += i * 4;
err_word = RREG32(err_addr); err_word = RREG32(err_addr);
if (err_word) { if (err_word) {
...@@ -6022,6 +6055,15 @@ static int gaudi_armcp_info_get(struct hl_device *hdev) ...@@ -6022,6 +6055,15 @@ static int gaudi_armcp_info_get(struct hl_device *hdev)
strncpy(prop->armcp_info.card_name, GAUDI_DEFAULT_CARD_NAME, strncpy(prop->armcp_info.card_name, GAUDI_DEFAULT_CARD_NAME,
CARD_NAME_MAX_LEN); CARD_NAME_MAX_LEN);
hdev->card_type = le32_to_cpu(hdev->asic_prop.armcp_info.card_type);
if (hdev->card_type == armcp_card_type_pci)
prop->max_power_default = MAX_POWER_DEFAULT_PCI;
else if (hdev->card_type == armcp_card_type_pmc)
prop->max_power_default = MAX_POWER_DEFAULT_PMC;
hdev->max_power = prop->max_power_default;
return 0; return 0;
} }
......
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
#define GAUDI_MAX_CLK_FREQ 2200000000ull /* 2200 MHz */ #define GAUDI_MAX_CLK_FREQ 2200000000ull /* 2200 MHz */
#define MAX_POWER_DEFAULT 200000 /* 200W */ #define MAX_POWER_DEFAULT_PCI 200000 /* 200W */
#define MAX_POWER_DEFAULT_PMC 350000 /* 350W */
#define GAUDI_CPU_TIMEOUT_USEC 15000000 /* 15s */ #define GAUDI_CPU_TIMEOUT_USEC 15000000 /* 15s */
......
...@@ -527,7 +527,7 @@ static int gaudi_config_etf(struct hl_device *hdev, ...@@ -527,7 +527,7 @@ static int gaudi_config_etf(struct hl_device *hdev,
} }
static bool gaudi_etr_validate_address(struct hl_device *hdev, u64 addr, static bool gaudi_etr_validate_address(struct hl_device *hdev, u64 addr,
u32 size, bool *is_host) u64 size, bool *is_host)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
struct gaudi_device *gaudi = hdev->asic_specific; struct gaudi_device *gaudi = hdev->asic_specific;
...@@ -539,6 +539,12 @@ static bool gaudi_etr_validate_address(struct hl_device *hdev, u64 addr, ...@@ -539,6 +539,12 @@ static bool gaudi_etr_validate_address(struct hl_device *hdev, u64 addr,
return false; return false;
} }
if (addr > (addr + size)) {
dev_err(hdev->dev,
"ETR buffer size %llu overflow\n", size);
return false;
}
/* PMMU and HPMMU addresses are equal, check only one of them */ /* PMMU and HPMMU addresses are equal, check only one of them */
if ((gaudi->hw_cap_initialized & HW_CAP_MMU) && if ((gaudi->hw_cap_initialized & HW_CAP_MMU) &&
hl_mem_area_inside_range(addr, size, hl_mem_area_inside_range(addr, size,
......
...@@ -139,6 +139,25 @@ static u16 goya_packet_sizes[MAX_PACKET_ID] = { ...@@ -139,6 +139,25 @@ static u16 goya_packet_sizes[MAX_PACKET_ID] = {
[PACKET_STOP] = sizeof(struct packet_stop) [PACKET_STOP] = sizeof(struct packet_stop)
}; };
static inline bool validate_packet_id(enum packet_id id)
{
switch (id) {
case PACKET_WREG_32:
case PACKET_WREG_BULK:
case PACKET_MSG_LONG:
case PACKET_MSG_SHORT:
case PACKET_CP_DMA:
case PACKET_MSG_PROT:
case PACKET_FENCE:
case PACKET_LIN_DMA:
case PACKET_NOP:
case PACKET_STOP:
return true;
default:
return false;
}
}
static u64 goya_mmu_regs[GOYA_MMU_REGS_NUM] = { static u64 goya_mmu_regs[GOYA_MMU_REGS_NUM] = {
mmDMA_QM_0_GLBL_NON_SECURE_PROPS, mmDMA_QM_0_GLBL_NON_SECURE_PROPS,
mmDMA_QM_1_GLBL_NON_SECURE_PROPS, mmDMA_QM_1_GLBL_NON_SECURE_PROPS,
...@@ -3455,6 +3474,12 @@ static int goya_validate_cb(struct hl_device *hdev, ...@@ -3455,6 +3474,12 @@ static int goya_validate_cb(struct hl_device *hdev,
PACKET_HEADER_PACKET_ID_MASK) >> PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT); PACKET_HEADER_PACKET_ID_SHIFT);
if (!validate_packet_id(pkt_id)) {
dev_err(hdev->dev, "Invalid packet id %u\n", pkt_id);
rc = -EINVAL;
break;
}
pkt_size = goya_packet_sizes[pkt_id]; pkt_size = goya_packet_sizes[pkt_id];
cb_parsed_length += pkt_size; cb_parsed_length += pkt_size;
if (cb_parsed_length > parser->user_cb_size) { if (cb_parsed_length > parser->user_cb_size) {
...@@ -3690,6 +3715,12 @@ static int goya_patch_cb(struct hl_device *hdev, ...@@ -3690,6 +3715,12 @@ static int goya_patch_cb(struct hl_device *hdev,
PACKET_HEADER_PACKET_ID_MASK) >> PACKET_HEADER_PACKET_ID_MASK) >>
PACKET_HEADER_PACKET_ID_SHIFT); PACKET_HEADER_PACKET_ID_SHIFT);
if (!validate_packet_id(pkt_id)) {
dev_err(hdev->dev, "Invalid packet id %u\n", pkt_id);
rc = -EINVAL;
break;
}
pkt_size = goya_packet_sizes[pkt_id]; pkt_size = goya_packet_sizes[pkt_id];
cb_parsed_length += pkt_size; cb_parsed_length += pkt_size;
if (cb_parsed_length > parser->user_cb_size) { if (cb_parsed_length > parser->user_cb_size) {
......
...@@ -362,11 +362,17 @@ static int goya_config_etf(struct hl_device *hdev, ...@@ -362,11 +362,17 @@ static int goya_config_etf(struct hl_device *hdev,
} }
static int goya_etr_validate_address(struct hl_device *hdev, u64 addr, static int goya_etr_validate_address(struct hl_device *hdev, u64 addr,
u32 size) u64 size)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
u64 range_start, range_end; u64 range_start, range_end;
if (addr > (addr + size)) {
dev_err(hdev->dev,
"ETR buffer size %llu overflow\n", size);
return false;
}
if (hdev->mmu_enable) { if (hdev->mmu_enable) {
range_start = prop->dmmu.start_addr; range_start = prop->dmmu.start_addr;
range_end = prop->dmmu.end_addr; range_end = prop->dmmu.end_addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment