Hi,

> -----Original Message-----
> From: Felipe Contreras [mailto:[email protected]]
> Sent: Thursday, May 13, 2010 3:47 PM
> To: linux-omap
> Cc: Ramirez Luna, Omar; Guzman Lugo, Fernando; Hiroshi Doyu; Felipe
> Contreras
> Subject: [PATCH 1/2] dspbridge: deh: fix corruption on MMU fault
> 
> ... by removing unnecessary fault handling.
> 
> From the looks of it, when an MMU fault happens, the DSP wants us to
> come up with the data that is supposed to be on the faulty address.
> Clearly, there's no way to provide that information, and such errors are
> fatal, so there's no point in allocating a buffer and mapping it.
> 
> Moreover, kmalloc() doesn't return paged memory, so if the DSP tries to
> write to an unaligned buffer, memory corruption ensures.
> 
> Based on the analysis of Fernando Guzman Lugo and Deepak Chitriki:
> http://article.gmane.org/gmane.linux.ports.arm.omap/34207
> 
> I tested a similar patch on Nokia custom hardware and memory corruption
> was gone. I tested this particular patch on a beagleboard, and although
> I was never able to reproduce the corruption, it didn't cause any
> further problems.
> 
> Signed-off-by: Felipe Contreras <[email protected]>
> ---
>  drivers/dsp/bridge/wmd/ue_deh.c |   28 ----------------------------
>  1 files changed, 0 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/dsp/bridge/wmd/ue_deh.c
> b/drivers/dsp/bridge/wmd/ue_deh.c
> index 03b29b6..233ad17 100644
> --- a/drivers/dsp/bridge/wmd/ue_deh.c
> +++ b/drivers/dsp/bridge/wmd/ue_deh.c
> @@ -62,13 +62,6 @@
>  /* Max time to check for GP Timer IRQ */
>  #define GPTIMER_IRQ_WAIT_MAX_CNT       1000
> 
> -static struct hw_mmu_map_attrs_t map_attrs = { HW_LITTLE_ENDIAN,
> -     HW_ELEM_SIZE16BIT,
> -     HW_MMU_CPUES
> -};
> -
> -static void *dummy_va_addr;
> -
>  static struct omap_dm_timer *timer;
> 
>  dsp_status bridge_deh_create(struct deh_mgr **ret_deh_mgr,
> @@ -84,7 +77,6 @@ dsp_status bridge_deh_create(struct deh_mgr
> **ret_deh_mgr,
>       /* Get WMD context info. */
>       dev_get_wmd_context(hdev_obj, &hwmd_context);
>       DBC_ASSERT(hwmd_context);
> -     dummy_va_addr = NULL;
>       /* Allocate IO manager object: */
>       deh_mgr = kzalloc(sizeof(struct deh_mgr), GFP_KERNEL);
>       if (!deh_mgr) {
> @@ -190,12 +182,8 @@ dsp_status bridge_deh_register_notify(struct deh_mgr
> *deh_mgr, u32 event_mask,
>  void bridge_deh_notify(struct deh_mgr *deh_mgr, u32 ulEventMask, u32
> dwErrInfo)
>  {
>       struct wmd_dev_context *dev_context;
> -     dsp_status status = DSP_SOK;
> -     u32 mem_physical = 0;
>       u32 hw_mmu_max_tlb_count = 31;
>       extern u32 fault_addr;
> -     struct cfg_hostres *resources;
> -     hw_status hw_status_obj;
>       u32 cnt = 0;
> 
>       if (!deh_mgr)
> @@ -203,7 +191,6 @@ void bridge_deh_notify(struct deh_mgr *deh_mgr, u32
> ulEventMask, u32 dwErrInfo)
> 
>       dev_info(bridge, "%s: device exception\n", __func__);
>       dev_context = (struct wmd_dev_context *)deh_mgr->hwmd_context;
> -     resources = dev_context->resources;
> 
>       switch (ulEventMask) {
>       case DSP_SYSERROR:
> @@ -228,9 +215,6 @@ void bridge_deh_notify(struct deh_mgr *deh_mgr, u32
> ulEventMask, u32 dwErrInfo)
>                       (unsigned int) deh_mgr->err_info.dw_val1,
>                       (unsigned int) deh_mgr->err_info.dw_val2,
>                       (unsigned int) fault_addr);
> -             dummy_va_addr = kzalloc(sizeof(char) * 0x1000, GFP_ATOMIC);
> -             mem_physical =
> -                     ALIGN_DOWN(virt_to_phys(dummy_va_addr), PAGE_SIZE);
>               dev_context = (struct wmd_dev_context *)
>                       deh_mgr->hwmd_context;
> 
> @@ -247,13 +231,6 @@ void bridge_deh_notify(struct deh_mgr *deh_mgr, u32
> ulEventMask, u32 dwErrInfo)
>                       dev_context->num_tlb_entries =
>                               dev_context->fixed_tlb_entries;
>               }
> -             if (DSP_SUCCEEDED(status)) {
> -                     hw_status_obj =
> -                             hw_mmu_tlb_add(resources->dw_dmmu_base,
> -                                             mem_physical, fault_addr,
> -                                             HW_PAGE_SIZE4KB, 1,
> -                                             &map_attrs, HW_SET, HW_SET);
> -             }
> 
>               /*
>                * Send a GP Timer interrupt to DSP.
> @@ -286,9 +263,6 @@ void bridge_deh_notify(struct deh_mgr *deh_mgr, u32
> ulEventMask, u32 dwErrInfo)
>                       }
>               }
> 
> -             /* Clear MMU interrupt */
> -             hw_mmu_event_ack(resources->dw_dmmu_base,
> -                             HW_MMU_TRANSLATION_FAULT);
>               dump_dsp_stack(deh_mgr->hwmd_context);

dump_dsp_stack is waiting DSP for dumping the stack, I don't think that you
are getting the complete dump with this patch.


Regards,
Fernando.

>               omap_dm_timer_disable(timer);
>               break;
> @@ -356,6 +330,4 @@ dsp_status bridge_deh_get_info(struct deh_mgr
> *deh_mgr,
> 
>  void bridge_deh_release_dummy_mem(void)
>  {
> -     kfree(dummy_va_addr);
> -     dummy_va_addr = NULL;
>  }
> --
> 1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to