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-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 20 Feb 2020 10:52:38 +0000
From:   John Garry <john.garry@...wei.com>
To:     Wei Xu <xuwei5@...ilicon.com>,
        Jiaxun Yang <jiaxun.yang@...goat.com>,
        bhelgaas <bhelgaas@...gle.com>,
        andyshevchenko <andy.shevchenko@...il.com>
CC:     Arnd Bergmann <arnd@...db.de>,
        linux-kernel <linux-kernel@...r.kernel.org>
Subject: Re: Questions about logic_pio

+ Arnd (also remove some defunct e-mail addresses)

On 20/02/2020 09:48, Wei Xu wrote:
> Hi Jiaxun,
> 
> On 2020/2/19 21:58, Jiaxun Yang wrote:
>> Hi there,
>>
>> Logic PIO gives us a way to make indirect PIO access, however,
>> the way it handles direct (MMIO) I/O access confused me.
>>
>> I was trying to create a PCI controller Driver and noticed that I/O range parsed
>> from DeviceTree will be added to the Logic PIO range by logic_pio_register_range.
>> And than PCI subsystem will use the ioport obtained from `logic_pio_trans_cpuaddr`
>> to allocate resources for the host bridge. In my case, the range added to the logic pio
>>   was set as hw_start 0x4000, size 0x4000.

FYI, For when CONFIG_INDIRECT_PIO is defined, in logical PIO space, we 
reserve the last 0x4000 bytes for Indirectio, while the rest is 
available for MMIO. When CONFIG_INDIRECT_PIO is not defined, all Logical 
PIO space is available for MMIO.

  Later, `logic_pio_trans_cpuaddr` called
>> by `pci_address_to_pio` gives a ioport of 0x0, which is totally wrong.

ioport of 0x0 seems fine. Here is my IO port listing for my host (which 
defines PCI_IOBASE):

00000000-0000ffff : PCI Bus 0002:f8
   00001000-00001fff : PCI Bus 0002:f9
     00001000-00001007 : 0002:f9:00.0
       00001000-00001007 : serial
     00001008-0000100f : 0002:f9:00.1
       00001008-0000100f : serial
     00001010-00001017 : 0002:f9:00.2
     00001018-0000101f : 0002:f9:00.2
00010000-0001ffff : PCI Bus 0004:88
00020000-0002ffff : PCI Bus 0005:78
00030000-0003ffff : PCI Bus 0006:c0
00040000-0004ffff : PCI Bus 0007:90
00050000-0005ffff : PCI Bus 000a:10
00060000-0006ffff : PCI Bus 000c:20
00070000-0007ffff : PCI Bus 000d:30
00ffc0e3-00ffc0e7 : hisi-lpc-ipmi.5.auto
00ffc2f7-00ffffff : serial8250.6.auto
   00ffc2f7-00ffc2fe : serial

>>
>> After dig into logic pio logic, I found that logic pio is trying to "allocate" an io_start
>> for MMIO ranges, the allocation starts from 0x0. And later the io_start is used to calculate
>> cpu_address.  In my opinion, for direct MMIO access, logic_pio address should always
>> equal to hw address,

I'm not sure what you mean by simply the hw address.

So there is the physical cpu address of the host bridge IO ports, and 
these host bridge IO ports are mapped in pci_remap_iospace() to some 
part of logical PIO space. The base of the logical PIO space corresponds 
to PCI_IOBASE virtual address.

  because there is no way to translate address from logic pio address
>> to actual hw address in {in,out}{b,sb,w,sb,l,sl} operations.

Please check 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/logic_pio.c?h=v5.6-rc2#n231 
for reference:

#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
#define BUILD_LOGIC_IO(bw, type)					\
type logic_in##bw(unsigned long addr)					\{									\	type ret = 
(type)~0;						\									\	if (addr < MMIO_UPPER_LIMIT) {					\		ret = 
read##bw(PCI_IOBASE + addr);			\	} else if (addr >= MMIO_UPPER_LIMIT && 
addr < IO_SPACE_LIMIT) { \		struct logic_pio_hwaddr *entry = 
find_io_range(addr);	\									\		if (entry)						\			ret = 
entry->ops->in(entry->hostdata,		\					addr, sizeof(type));		\		else				 
		\			WARN_ON_ONCE(1);				\	}								\	return ret;							\}											

For when the IO port address is within the MMIO range (addr < 
MMIO_UPPER_LIMIT), we use readl(PCI_IOBASE + addr); please remember that 
PCI_IOBASE virtual address is mapped to the physical host bridge IO port 
address.

For when CONFIG_INDIRECT_PIO is not defined, we use the asm generic version:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/io.h?h=v5.6-rc2#n461

As an aside, I do notice that the definitions here have changed here in 
87fe2d543f81 ("io: change inX() to have their own IO barrier overrides") 
since we introduced logic PIO.

>>
>> How this mechanism intends to work? 

I hope the above description makes this clearer.

What is the reason that we are trying to
>> allocate a io_start for MMIO rather than take their hw_start ioport directly?

For PCI MMIO, the io_start is the Logical PIO range start address.

>>
>> Thanks.
> 
> Corrected John's mail address.
> Maybe he can help.

Thanks to xuwei

> 
> Best Regards,
> Wei
> 
>>
>> --
>> Jiaxun Yang
>>
>>
>>
>> .
>>
> 
> .
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ