[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4 1/3] xen/riscv: introduce setup_initial_pages



Hi Jan,

On Mon, 2023-04-17 at 13:50 +0200, Jan Beulich wrote:
> On 07.04.2023 17:48, Oleksii Kurochko wrote:
> > The idea was taken from xvisor but the following changes
> > were done:
> > * Use only a minimal part of the code enough to enable MMU
> > * rename {_}setup_initial_pagetables functions
> > * add an argument for setup_initial_mapping to have
> >   an opportunity to make set PTE flags.
> > * update setup_initial_pagetables function to map sections
> >   with correct PTE flags.
> > * Rewrite enable_mmu() to C.
> > * map linker addresses range to load addresses range without
> >   1:1 mapping. It will be 1:1 only in case when
> >   load_start_addr is equal to linker_start_addr.
> > * add safety checks such as:
> >   * Xen size is less than page size
> >   * linker addresses range doesn't overlap load addresses
> >     range
> > * Rework macros {THIRD,SECOND,FIRST,ZEROETH}_{SHIFT,MASK}
> > * change PTE_LEAF_DEFAULT to RW instead of RWX.
> > * Remove phys_offset as it is not used now
> > * Remove alignment  of {map, pa}_start &= XEN_PT_LEVEL_MAP_MASK(0);
> >   in  setup_inital_mapping() as they should be already aligned.
> >   Make a check that {map_pa}_start are aligned.
> > * Remove clear_pagetables() as initial pagetables will be
> >   zeroed during bss initialization
> > * Remove __attribute__((section(".entry")) for
> > setup_initial_pagetables()
> >   as there is no such section in xen.lds.S
> > * Update the argument of pte_is_valid() to "const pte_t *p"
> > * Add check that Xen's load address is aligned at 4k boundary
> > * Refactor setup_initial_pagetables() so it is mapping linker
> >   address range to load address range. After setup needed
> >   permissions for specific section ( such as .text, .rodata, etc )
> >   otherwise RW permission will be set by default.
> > * Add function to check that requested SATP_MODE is supported
> > 
> > Origin: git@xxxxxxxxxx:xvisor/xvisor.git 9be2fdd7
> > Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
> > ---
> > Changes in V4:
> >   * use GB() macros instead of defining SZ_1G
> >   * hardcode XEN_VIRT_START and add comment (ADDRESS_SPACE_END + 1
> > - GB(1))
> 
> Perhaps in a separate patch, may I ask that you add - like x86 and
> Arm
> have it - a block comment to config.h laying out virtual address
> space
> use? Knowing what is planned to be put where (even if just vaguely,
> i.e.
> keeping open the option of changing the layout) is likely going to
> help
> with figuring whether this is a good placement.
> 
> Such a comment could then also be accompanied by mentioning that
> virtual address space really "wraps" at certain boundaries (due to
> the
> upper address bits simply being ignored). For an x86 person like me
> this is certainly unexpected / unusual behavior.
> 
Sure, it makes sense. I'll add that to new version of the patch series.

> >   * remove unnecessary 'asm' word at the end of #error
> >   * encapsulate pte_t definition in a struct
> >   * rename addr_to_ppn() to ppn_to_paddr().
> >   * change type of paddr argument from const unsigned long to
> > paddr_t
> >   * pte_to_paddr() update prototype.
> >   * calculate size of Xen binary based on an amount of page tables
> >   * use unsgined int instead of 'uint32_t' instead of uint32_t as
> >     their use isn't warranted.
> >   * remove extern of bss_{start,end} as they aren't used in mm.c
> > anymore
> >   * fix code style
> >   * add argument for HANDLE_PGTBL macros instead of curr_lvl_num
> > variable
> >   * make enable_mmu() as noinline to prevent under link-time
> > optimization
> >     because of the nature of enable_mmu()
> >   * add function to check that SATP_MODE is supported.
> >   * update the commit message
> >   * update setup_initial_pagetables to set correct PTE flags in one
> > pass
> >     instead of calling setup_pte_permissions after
> > setup_initial_pagetables()
> >     as setup_initial_pagetables() isn't used to change permission
> > flags.
> > ---
> > Changes in V3:
> >  - update definition of pte_t structure to have a proper size of
> > pte_t
> >    in case of RV32.
> >  - update asm/mm.h with new functions and remove unnecessary
> > 'extern'.
> >  - remove LEVEL_* macros as only XEN_PT_LEVEL_* are enough.
> >  - update paddr_to_pte() to receive permissions as an argument.
> >  - add check that map_start & pa_start is properly aligned.
> >  - move  defines PAGETABLE_ORDER, PAGETABLE_ENTRIES, PTE_PPN_SHIFT
> > to
> >    <asm/page-bits.h>
> >  - Rename PTE_SHIFT to PTE_PPN_SHIFT
> >  - refactor setup_initial_pagetables: map all LINK addresses to
> > LOAD addresses
> >    and after setup PTEs permission for sections; update check that
> > linker
> >    and load addresses don't overlap.
> >  - refactor setup_initial_mapping: allocate pagetable 'dynamically'
> > if it is
> >    necessary.
> >  - rewrite enable_mmu in C; add the check that map_start and
> > pa_start are
> >    aligned on 4k boundary.
> >  - update the comment for setup_initial_pagetable funcion
> >  - Add RV_STAGE1_MODE to support different MMU modes
> >  - set XEN_VIRT_START very high to not overlap with load address
> > range
> >  - align bss section
> > ---
> > Changes in V2:
> >  * update the commit message:
> >  * Remove {ZEROETH,FIRST,...}_{SHIFT,MASK, SIZE,...} and
> >    introduce instead of them XEN_PT_LEVEL_*() and LEVEL_*
> >  * Rework pt_linear_offset() and pt_index based on 
> > XEN_PT_LEVEL_*()
> >  * Remove clear_pagetables() functions as pagetables were zeroed
> > during
> >    .bss initialization
> >  * Rename _setup_initial_pagetables() to setup_initial_mapping()
> >  * Make PTE_DEFAULT equal to RX.
> >  * Update prototype of setup_initial_mapping(..., bool writable) ->
> >    setup_initial_mapping(..., UL flags)  
> >  * Update calls of setup_initial_mapping according to new prototype
> >  * Remove unnecessary call of:
> >    _setup_initial_pagetables(..., load_addr_start, load_addr_end,
> > load_addr_start, ...)
> >  * Define index* in the loop of setup_initial_mapping
> >  * Remove attribute "__attribute__((section(".entry")))" for
> > setup_initial_pagetables()
> >    as we don't have such section
> >  * make arguments of paddr_to_pte() and pte_is_valid() as const.
> >  * make xen_second_pagetable static.
> >  * use <xen/kernel.h> instead of declaring extern unsigned long
> > _stext, 0etext, _srodata, _erodata
> >  * update  'extern unsigned long __init_begin' to 'extern unsigned
> > long __init_begin[]'
> >  * use aligned() instead of
> > "__attribute__((__aligned__(PAGE_SIZE)))"
> >  * set __section(".bss.page_aligned") for page tables arrays
> >  * fix identatations
> >  * Change '__attribute__((section(".entry")))' to '__init'
> >  * Remove phys_offset as it isn't used now.
> >  * Remove alignment  of {map, pa}_start &=
> > XEN_PT_LEVEL_MAP_MASK(0); in
> >    setup_inital_mapping() as they should be already aligned.
> >  * Remove clear_pagetables() as initial pagetables will be
> >    zeroed during bss initialization
> >  * Remove __attribute__((section(".entry")) for
> > setup_initial_pagetables()
> >    as there is no such section in xen.lds.S
> >  * Update the argument of pte_is_valid() to "const pte_t *p"
> > ---
> > 
> >  xen/arch/riscv/Makefile                |   1 +
> >  xen/arch/riscv/include/asm/config.h    |  12 +-
> >  xen/arch/riscv/include/asm/mm.h        |   9 +
> >  xen/arch/riscv/include/asm/page-bits.h |  10 +
> >  xen/arch/riscv/include/asm/page.h      |  65 +++++
> >  xen/arch/riscv/mm.c                    | 319
> > +++++++++++++++++++++++++
> >  xen/arch/riscv/riscv64/head.S          |   2 +
> >  xen/arch/riscv/setup.c                 |  11 +
> >  xen/arch/riscv/xen.lds.S               |   4 +
> >  9 files changed, 432 insertions(+), 1 deletion(-)
> >  create mode 100644 xen/arch/riscv/include/asm/mm.h
> >  create mode 100644 xen/arch/riscv/include/asm/page.h
> >  create mode 100644 xen/arch/riscv/mm.c
> > 
> > diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
> > index 443f6bf15f..956ceb02df 100644
> > --- a/xen/arch/riscv/Makefile
> > +++ b/xen/arch/riscv/Makefile
> > @@ -1,5 +1,6 @@
> >  obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
> >  obj-y += entry.o
> > +obj-y += mm.o
> >  obj-$(CONFIG_RISCV_64) += riscv64/
> >  obj-y += sbi.o
> >  obj-y += setup.o
> > diff --git a/xen/arch/riscv/include/asm/config.h
> > b/xen/arch/riscv/include/asm/config.h
> > index 763a922a04..0cf9673558 100644
> > --- a/xen/arch/riscv/include/asm/config.h
> > +++ b/xen/arch/riscv/include/asm/config.h
> > @@ -39,12 +39,22 @@
> >    name:
> >  #endif
> >  
> > -#define XEN_VIRT_START  _AT(UL, 0x80200000)
> > +#ifdef CONFIG_RISCV_64
> > +#define XEN_VIRT_START 0xFFFFFFFFC0000000 /* (_AC(-1, UL) + 1 -
> > GB(1)) */
> > +#else
> > +#error "RV32 isn't supported"
> > +#endif
> >  
> >  #define SMP_CACHE_BYTES (1 << 6)
> >  
> >  #define STACK_SIZE PAGE_SIZE
> >  
> > +#ifdef CONFIG_RISCV_64
> > +#define RV_STAGE1_MODE SATP_MODE_SV39
> > +#else
> > +#define RV_STAGE1_MODE SATP_MODE_SV32
> > +#endif
> > +
> >  #endif /* __RISCV_CONFIG_H__ */
> >  /*
> >   * Local variables:
> > diff --git a/xen/arch/riscv/include/asm/mm.h
> > b/xen/arch/riscv/include/asm/mm.h
> > new file mode 100644
> > index 0000000000..e16ce66fae
> > --- /dev/null
> > +++ b/xen/arch/riscv/include/asm/mm.h
> > @@ -0,0 +1,9 @@
> > +#ifndef _ASM_RISCV_MM_H
> > +#define _ASM_RISCV_MM_H
> > +
> > +void setup_initial_pagetables(void);
> > +
> > +void enable_mmu(void);
> > +void cont_after_mmu_is_enabled(void);
> > +
> > +#endif /* _ASM_RISCV_MM_H */
> > diff --git a/xen/arch/riscv/include/asm/page-bits.h
> > b/xen/arch/riscv/include/asm/page-bits.h
> > index 1801820294..0879a527f2 100644
> > --- a/xen/arch/riscv/include/asm/page-bits.h
> > +++ b/xen/arch/riscv/include/asm/page-bits.h
> > @@ -1,6 +1,16 @@
> >  #ifndef __RISCV_PAGE_BITS_H__
> >  #define __RISCV_PAGE_BITS_H__
> >  
> > +#ifdef CONFIG_RISCV_64
> > +#define PAGETABLE_ORDER         (9)
> > +#else /* CONFIG_RISCV_32 */
> > +#define PAGETABLE_ORDER         (10)
> > +#endif
> > +
> > +#define PAGETABLE_ENTRIES       (1 << PAGETABLE_ORDER)
> > +
> > +#define PTE_PPN_SHIFT           10
> > +
> >  #define PAGE_SHIFT              12 /* 4 KiB Pages */
> >  #define PADDR_BITS              56 /* 44-bit PPN */
> >  
> > diff --git a/xen/arch/riscv/include/asm/page.h
> > b/xen/arch/riscv/include/asm/page.h
> > new file mode 100644
> > index 0000000000..30406aa614
> > --- /dev/null
> > +++ b/xen/arch/riscv/include/asm/page.h
> > @@ -0,0 +1,65 @@
> > +#ifndef _ASM_RISCV_PAGE_H
> > +#define _ASM_RISCV_PAGE_H
> > +
> > +#include <xen/const.h>
> > +#include <xen/types.h>
> > +
> > +#define VPN_MASK                    ((unsigned
> > long)(PAGETABLE_ENTRIES - 1))
> > +
> > +#define XEN_PT_LEVEL_ORDER(lvl)     ((lvl) * PAGETABLE_ORDER)
> > +#define XEN_PT_LEVEL_SHIFT(lvl)     (XEN_PT_LEVEL_ORDER(lvl) +
> > PAGE_SHIFT)
> > +#define XEN_PT_LEVEL_SIZE(lvl)      (_AT(paddr_t, 1) <<
> > XEN_PT_LEVEL_SHIFT(lvl))
> > +#define XEN_PT_LEVEL_MAP_MASK(lvl)  (~(XEN_PT_LEVEL_SIZE(lvl) -
> > 1))
> > +#define XEN_PT_LEVEL_MASK(lvl)      (VPN_MASK <<
> > XEN_PT_LEVEL_SHIFT(lvl))
> > +
> > +#define PTE_VALID                   BIT(0, UL)
> > +#define PTE_READABLE                BIT(1, UL)
> > +#define PTE_WRITABLE                BIT(2, UL)
> > +#define PTE_EXECUTABLE              BIT(3, UL)
> > +#define PTE_USER                    BIT(4, UL)
> > +#define PTE_GLOBAL                  BIT(5, UL)
> > +#define PTE_ACCESSED                BIT(6, UL)
> > +#define PTE_DIRTY                   BIT(7, UL)
> > +#define PTE_RSW                     (BIT(8, UL) | BIT(9, UL))
> > +
> > +#define PTE_LEAF_DEFAULT            (PTE_VALID | PTE_READABLE |
> > PTE_WRITABLE)
> > +#define PTE_TABLE                   (PTE_VALID)
> > +
> > +/* Calculate the offsets into the pagetables for a given VA */
> > +#define pt_linear_offset(lvl, va)   ((va) >>
> > XEN_PT_LEVEL_SHIFT(lvl))
> > +
> > +#define pt_index(lvl, va) pt_linear_offset(lvl, (va) &
> > XEN_PT_LEVEL_MASK(lvl))
> > +
> > +/* Page Table entry */
> > +typedef struct {
> > +#ifdef CONFIG_RISCV_64
> > +uint64_t pte;
> > +#else
> > +uint32_t pte;
> > +#endif
> > +} pte_t;
> 
> Please indent both field declarations accordingly.
> 
> > +#define addr_to_pte(x) (((x) >> PTE_PPN_SHIFT) << PAGE_SHIFT)
> 
> This still looks to be converting _to_ an address, not to PTE layout,
> ...
> 
> > +/* Shift the VPN[x] or PPN[x] fields of a virtual or physical
> > address
> > + * to become the shifted PPN[x] fields of a page table entry */
> > +#define ppn_to_paddr(x) (((x) >> PAGE_SHIFT) << PTE_PPN_SHIFT)
> 
> ... while this converts an address (not a ppn) to PTE layout (not a
> paddr). Getting the names of these helpers right is crucial for easy
> following of any code using them. To be honest, I'll stop reviewing
> here, because the names being wrong is just going to be too
> confusing.
You are right the names are confusing and should be renamed.
Thanks.

~ Oleksii




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.