lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Sat, 23 Sep 2006 12:29:08 -0400
From:	Robin Getz <rgetz@...ckfin.uclinux.org>
To:	Arnd Bergmann <arnd@...db.de>
Cc:	Mike Frysinger <vapier.adi@...il.com>,
	linux-kernel@...r.kernel.org, Andrew Morton <akpm@...l.org>,
	Luke Yang <luke.adi@...il.com>
Subject: Re: [PATCH 1/4] Blackfin: arch patch for 2.6.18

Arnd provide some feedback:
>On Saturday 23 September 2006 13:15, Mike Frysinger wrote:
> > On 9/23/06, Arnd Bergmann <arnd@...db.de> wrote:
> > > On Saturday 23 September 2006 08:50, Mike Frysinger wrote:
> > > > On 9/22/06, Arnd Bergmann <arnd@...db.de> wrote:
>
> > > > > What's the point, are you getting paid by lines of code? Just use
> > > > > the registers directly!
> > > >
> > > > in our last submission we were doing exactly that ... and we were told
> > > > to switch to a function style method of reading/writing memory mapped
> > > > registers
> > >
> > > It's hard to imagine that what you have here was intended by the comment
> > > then. Do you have an archive link about that discussion?
> >
> > no as i was not around for said discussion.  but it should be in the
> > threads covering the submission of blackfin for 2.6.13 ...
>
>Ok, I found http://marc.theaimsgroup.com/?l=linux-kernel&m=114298753207549&w=2
>from akpm, and I fear you heavily misunderstood him.
>
>Your original patch had code like
>
>/* System Reset and Interrupt Controller registers for core A (0xFFC0 
>0100-0xFFC0 01FF) */
>#define SICA_SWRST              0xFFC00100·····/* Software Reset register */
>[snip]
>...
>
>#define pSICA_SWRST (volatile unsigned short *)SICA_SWRST
>[snip]
>
>static void bf561_internal_mask_irq(unsigned int irq)
>{
>         unsigned long irq_mask;
>         if ((irq - (IRQ_CORETMR + 1)) < 32) {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
>                 pSICA_IMASK0 &= ~irq_mask;
>         } else {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
>                 pSICA_IMASK1 &= ~irq_mask;
>         }
>}
>
>which Andrew objected to, on multiple grounds. You now converted this to
>
>/* System Reset and Interrupt Controller registers for core A (0xFFC0 
>0100-0xFFC0 01FF) */
>#define SICA_SWRST              0xFFC00100·····/* Software Reset register */
>[snip]
>/* System Reset and Interrupt Controller registers for core A (0xFFC0 
>0100-0xFFC0 01FF) */
>#define bfin_read_SICA_SWRST()               bfin_read16(SICA_SWRST)
>[snip]
>
>...
>static void bf561_internal_mask_irq(unsigned int irq)
>{
>         unsigned long irq_mask;
>         if ((irq - (IRQ_CORETMR + 1)) < 32) {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
>                 bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask);
>         } else {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
>                 bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask);
>         }
>}
>
>which is about just as bad, but for different reasons.

I would be interested in the reasons why this is bad. We thought is solved 
the problem, and our driver developers are Ok using it, and it is catching 
more problems at compile time than we use to (which is the main reason I 
thought to remove all the volatile casting.

>Now, there are
>at least two common methods for how to do this better, both involving
>the readl/writel low-level accessors (or something similar).

The thing to understand about the Blackfin architecture - is not all system 
register, or peripheral registers are 32 bits. Some are 16 bits, and some 
are 32. The Hardware will error if you access a 32 bit instruction, with a 
16 bit access, or a 16 bit access on a 32 bit instruction.

This is why we added:
bfin_write16();  bfin_read16(); bfin_write32();  bfin_read32();

We can't use a common function, like:

bfin_sica_read(int reg)

or use the read16/read32 directly - it would be to hard for the driver 
developers to keep the manual with them all the time to find out if a 
register was 16 or 32 bits. It would move what we have today (compiler 
errors), to run time errors if someone used the wrong function.

>The first one uses enumerated register numers:
>
>/* System Reset and Interrupt Controller registers for core A (0xFFC0 
>0100-0xFFC0 01FF) */
>
>enum bfin_sica_regs {
>         SICA_SWRST   = 100,·····/* Software Reset register */
>         SICA_SYSCR   = 104,·····/* System Reset Configuration register */
>         SICA_RVECT   = 108,·····/* SIC Reset Vector Address Register */
>         SICA_IMASK   = 10C,·····/* SIC Interrupt Mask register 0 - hack 
> to fix old tests */
>         SICA_IMASK0  = 10C,·····/* SIC Interrupt Mask register 0 */
>         SICA_IMASK1  = 110,·····/* SIC Interrupt Mask register 1 */
>         SICA_IAR0    = 124,·····/* SIC Interrupt Assignment Register 0 */
>         SICA_IAR1    = 128,·····/* SIC Interrupt Assignment Register 1 */
>         SICA_IAR2    = 12C,·····/* SIC Interrupt Assignment Register 2 */
>         SICA_IAR3    = 130,·····/* SIC Interrupt Assignment Register 3 */
>         SICA_IAR4    = 134,·····/* SIC Interrupt Assignment Register 4 */
>         SICA_IAR5    = 138,·····/* SIC Interrupt Assignment Register 5 */
>         SICA_IAR6    = 13C,·····/* SIC Interrupt Assignment Register 6 */
>         SICA_IAR7    = 140,·····/* SIC Interrupt Assignment Register 7 */
>         SICA_ISR0    = 114,·····/* SIC Interrupt Status register 0 */
>         SICA_ISR1    = 118,·····/* SIC Interrupt Status register 1 */
>         SICA_IWR0    = 11C,·····/* SIC Interrupt Wakeup-Enable register 0 */
>         SICA_IWR1    = 120,·····/* SIC Interrupt Wakeup-Enable register 1 */
>};
>
>...
>
>static void __iomem *bfin_sica = (void __iomem *)0xffc00100ul;
>static inline __le32 bfin_sica_read(int reg)
>{
>         return (__le32)readl(bfin_sica + reg);
>}
>
>static inline void bfin_sica_write(int reg, __le32 val)
>{
>         writel((uint32_t)val, bfin_sica + reg);
>}
>
>static void bf561_internal_mask_irq(unsigned int irq)
>{
>         unsigned long irq_mask;
>         if ((irq - (IRQ_CORETMR + 1)) < 32) {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
>                 bfin_sica_write(SICA_IMASK0,
>                         bfin_sica_read(SICA_IMASK0) & ~irq_mask);
>         } else {
>                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
>                 bfin_sica_write(SICA_IMASK0,
>                         bfin_sica_read(SICA_IMASK0) & ~irq_mask);
>         }
>}
>
>The alternative approach uses a structure:

We could use this approach, filling it up with 16 bit padding all over the 
place (which is easy to do), but it is also difficult for the same reason. 
(Although I really like this, and can see lots of value from it - I am not 
sure we can use it).

You are still using writel(reg, value) and readl(reg) - which is hard to 
do, without a hardware reference beside you all the time - to determine 
which time you should use a readl or reads.

Unless I am completely missing something (which might be true).


>/* System Reset and Interrupt Controller registers for core A (0xFFC0 
>0100-0xFFC0 01FF) */
>
>struct bfin_sica_regs {
>         __le32 swrst;   /* Software Reset register */
>         __le32 syscr;   /* System Reset Configuration register */
>         __le32 rvect;   /* SIC Reset Vector Address Register */
>         __le32 imask[2]; /* SIC Interrupt Mask register 0-1 */
>         __le32 iar[8];  /* SIC Interrupt Assignment Register 0-7 */
>         __le32 isr[2];  /* SIC Interrupt Status register 0-1 */
>         __le32 iwr[2];  /* SIC Interrupt Wakeup-Enable register 0-2 */
>};
>
>...
>
>static struct bfin_sica_regs __iomem *bfin_sica = (void __iomem 
>*)0xffc00100ul;
>
>static void bf561_internal_mask_irq(unsigned int irq)
>{
>         int irqnr = irq - (IRQ_CORETMR + 1);
>         __le32 __iomem *reg = &bfin_sica->imask[irqnr >> 5];
>         unsigned long irq_mask = 1 << (irqnr & 0x1f);
>
>         writel(reg, readl(reg) & ~irq_mask);
>}
>
>I'd personally prefer the last approach because of its compactness.
>
>         Arnd <><

Although I think the code is smaller, and nicer - it involves more run time 
complexity, and will consume more processor cycles - the old example:

static void bf561_internal_mask_irq(unsigned int irq)
{
         unsigned long irq_mask;
         if ((irq - (IRQ_CORETMR + 1)) < 32) {
                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
                 bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask);
         } else {
                 irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
                 bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask);
         }
}

resolves all addresses at compile time, not run time. So, wouldn't your 
example slow things down?

-Robin 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ