On 2023/12/08 0:54, Alexander Gordeev wrote:
Rework VTOP and PTOV macros to reflect the future
uncoupling of physical and virtual address spaces
in kernel. Existing versions are not affected.
Signed-off-by: Alexander Gordeev <agordeev(a)linux.ibm.com>
For the series with the 3/3 v3,
Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Thanks,
Kazu
> ---
> defs.h | 20 +++++-
> s390x.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 228 insertions(+), 4 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 5218a94..20237b7 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -4564,9 +4564,9 @@ struct efi_memory_desc_t {
> #define _64BIT_
> #define MACHINE_TYPE "S390X"
>
> -#define PTOV(X) ((unsigned long)(X)+(machdep->kvbase))
> -#define VTOP(X) ((unsigned long)(X)-(machdep->kvbase))
> -#define IS_VMALLOC_ADDR(X) (vt->vmalloc_start && (ulong)(X) >=
vt->vmalloc_start)
> +#define PTOV(X) s390x_PTOV((ulong)(X))
> +#define VTOP(X) s390x_VTOP((ulong)(X))
> +#define IS_VMALLOC_ADDR(X) s390x_IS_VMALLOC_ADDR(X)
> #define PTRS_PER_PTE 512
> #define PTRS_PER_PMD 1024
> #define PTRS_PER_PGD 2048
> @@ -6827,7 +6827,21 @@ void get_s390_panicmsg(char *);
> * s390x.c
> */
> #ifdef S390X
> +
> +struct machine_specific
> +{
> + ulong (*virt_to_phys)(ulong vaddr);
> + ulong (*phys_to_virt)(ulong paddr);
> + int (*is_vmalloc_addr)(ulong vaddr);
> + ulong __kaslr_offset_phys;
> + ulong amode31_start;
> + ulong amode31_end;
> +};
> +
> void s390x_init(int);
> +ulong s390x_PTOV(ulong);
> +ulong s390x_VTOP(ulong);
> +int s390x_IS_VMALLOC_ADDR(ulong);
> void s390x_dump_machdep_table(ulong);
> #define display_idt_table() \
> error(FATAL, "-d option is not applicable to S390X
architecture\n")
> diff --git a/s390x.c b/s390x.c
> index 4024d84..54b4ebc 100644
> --- a/s390x.c
> +++ b/s390x.c
> @@ -47,6 +47,7 @@
> #define S390X_PSW_MASK_PSTATE 0x0001000000000000UL
>
> #define S390X_LC_VMCORE_INFO 0xe0c
> +#define S390X_LC_OS_INFO 0xe18
>
> /*
> * Flags for Region and Segment table entries.
> @@ -168,6 +169,19 @@ static struct line_number_hook s390x_line_number_hooks[];
> static int s390x_is_uvaddr(ulong, struct task_context *);
> static int s390x_get_kvaddr_ranges(struct vaddr_range *);
> static int set_s390x_max_physmem_bits(void);
> +static ulong s390x_generic_VTOP(ulong vaddr);
> +static ulong s390x_generic_PTOV(ulong paddr);
> +static int s390x_generic_IS_VMALLOC_ADDR(ulong vaddr);
> +static ulong s390x_vr_VTOP(ulong vaddr);
> +static ulong s390x_vr_PTOV(ulong paddr);
> +static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr);
> +static int s390x_vr_is_kvaddr(ulong);
> +
> +struct machine_specific s390x_machine_specific = {
> + .virt_to_phys = s390x_generic_VTOP,
> + .phys_to_virt = s390x_generic_PTOV,
> + .is_vmalloc_addr = s390x_generic_IS_VMALLOC_ADDR,
> +};
>
> /*
> * struct lowcore name (old: "_lowcore", new: "lowcore")
> @@ -546,6 +560,191 @@ static void s390x_check_kaslr(void)
> free(vmcoreinfo);
> }
>
> +#define OS_INFO_VERSION_MAJOR 1
> +#define OS_INFO_VERSION_MINOR 1
> +
> +#define OS_INFO_VMCOREINFO 0
> +#define OS_INFO_REIPL_BLOCK 1
> +#define OS_INFO_FLAGS_ENTRY 2
> +#define OS_INFO_RESERVED 3
> +#define OS_INFO_IDENTITY_BASE 4
> +#define OS_INFO_KASLR_OFFSET 5
> +#define OS_INFO_KASLR_OFF_PHYS 6
> +#define OS_INFO_VMEMMAP 7
> +#define OS_INFO_AMODE31_START 8
> +#define OS_INFO_AMODE31_END 9
> +
> +struct os_info_entry {
> + union {
> + __u64 addr;
> + __u64 val;
> + };
> + __u64 size;
> + __u32 csum;
> +} __attribute__((packed));
> +
> +struct os_info {
> + __u64 magic;
> + __u32 csum;
> + __u16 version_major;
> + __u16 version_minor;
> + __u64 crashkernel_addr;
> + __u64 crashkernel_size;
> + struct os_info_entry entry[10];
> + __u8 reserved[3864];
> +} __attribute__((packed));
> +
> +struct vm_info {
> + __u64 __identity_base;
> + __u64 __kaslr_offset;
> + __u64 __kaslr_offset_phys;
> + __u64 amode31_start;
> + __u64 amode31_end;
> +};
> +
> +static bool
> +vmcoreinfo_read_u64(const char *key, __u64 *val)
> +{
> + char *string;
> +
> + string = pc->read_vmcoreinfo(key);
> + if (string) {
> + *val = strtoul(string, NULL, 16);
> + free(string);
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static bool vmcoreinfo_read_vm_info(struct vm_info *_vm_info)
> +{
> + struct vm_info vm_info;
> +
> + if (!vmcoreinfo_read_u64("IDENTITYBASE", &vm_info.__identity_base)
||
> + !vmcoreinfo_read_u64("KERNELOFFSET", &vm_info.__kaslr_offset)
||
> + !vmcoreinfo_read_u64("KERNELOFFPHYS",
&vm_info.__kaslr_offset_phys) ||
> + !vmcoreinfo_read_u64("SAMODE31", &vm_info.amode31_start)
||
> + !vmcoreinfo_read_u64("EAMODE31", &vm_info.amode31_end))
> + return false;
> +
> + *_vm_info = vm_info;
> +
> + return true;
> +}
> +
> +static bool os_info_read_vm_info(struct vm_info *vm_info)
> +{
> + struct os_info os_info;
> + ulong addr;
> +
> + if (!readmem(S390X_LC_OS_INFO, PHYSADDR, &addr,
> + sizeof(addr), "s390x os_info ptr",
> + QUIET|RETURN_ON_ERROR))
> + return false;
> +
> + if (addr == 0)
> + return true;
> +
> + if (!readmem(addr, PHYSADDR, &os_info,
> + offsetof(struct os_info, reserved), "s390x os_info header",
> + QUIET|RETURN_ON_ERROR))
> + return false;
> +
> + vm_info->__identity_base = os_info.entry[OS_INFO_IDENTITY_BASE].val;
> + vm_info->__kaslr_offset = os_info.entry[OS_INFO_KASLR_OFFSET].val;
> + vm_info->__kaslr_offset_phys = os_info.entry[OS_INFO_KASLR_OFF_PHYS].val;
> + vm_info->amode31_start = os_info.entry[OS_INFO_AMODE31_START].val;
> + vm_info->amode31_end = os_info.entry[OS_INFO_AMODE31_END].val;
> +
> + return true;
> +}
> +
> +static bool vm_info_empty(struct vm_info *vm_info)
> +{
> + return !vm_info->__kaslr_offset;
> +}
> +
> +static bool s390x_init_vm(void)
> +{
> + struct vm_info vm_info;
> +
> + if (pc->flags & PROC_KCORE) {
> + if (!vmcoreinfo_read_vm_info(&vm_info))
> + return true;
> + } else {
> + if (!os_info_read_vm_info(&vm_info))
> + return false;
> + }
> + if (vm_info_empty(&vm_info))
> + return true;
> +
> + machdep->identity_map_base = vm_info.__identity_base;
> + machdep->kvbase = vm_info.__kaslr_offset;
> + machdep->machspec->__kaslr_offset_phys = vm_info.__kaslr_offset_phys;
> + machdep->machspec->amode31_start = vm_info.amode31_start;
> + machdep->machspec->amode31_end = vm_info.amode31_end;
> +
> + machdep->is_kvaddr = s390x_vr_is_kvaddr;
> + machdep->machspec->virt_to_phys = s390x_vr_VTOP;
> + machdep->machspec->phys_to_virt = s390x_vr_PTOV;
> + machdep->machspec->is_vmalloc_addr = s390x_vr_IS_VMALLOC_ADDR;
> +
> + return true;
> +}
> +
> +static ulong s390x_generic_VTOP(ulong vaddr)
> +{
> + return vaddr - machdep->kvbase;
> +}
> +
> +static ulong s390x_generic_PTOV(ulong paddr)
> +{
> + return paddr + machdep->kvbase;
> +}
> +
> +static int s390x_generic_IS_VMALLOC_ADDR(ulong vaddr)
> +{
> + return vt->vmalloc_start && vaddr >= vt->vmalloc_start;
> +}
> +
> +static ulong s390x_vr_VTOP(ulong vaddr)
> +{
> + if (vaddr < LOWCORE_SIZE)
> + return vaddr;
> + if ((vaddr < machdep->machspec->amode31_end) &&
> + (vaddr >= machdep->machspec->amode31_start))
> + return vaddr;
> + if (vaddr < machdep->kvbase)
> + return vaddr - machdep->identity_map_base;
> + return vaddr - machdep->kvbase + machdep->machspec->__kaslr_offset_phys;
> +}
> +
> +static ulong s390x_vr_PTOV(ulong paddr)
> +{
> + return paddr + machdep->identity_map_base;
> +}
> +
> +static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr)
> +{
> + return (vaddr >= vt->vmalloc_start && vaddr <
machdep->kvbase);
> +}
> +
> +ulong s390x_VTOP(ulong vaddr)
> +{
> + return machdep->machspec->virt_to_phys(vaddr);
> +}
> +
> +ulong s390x_PTOV(ulong paddr)
> +{
> + return machdep->machspec->phys_to_virt(paddr);
> +}
> +
> +int s390x_IS_VMALLOC_ADDR(ulong vaddr)
> +{
> + return machdep->machspec->is_vmalloc_addr(vaddr);
> +}
> +
> /*
> * Do all necessary machine-specific setup here. This is called several
> * times during initialization.
> @@ -560,6 +759,7 @@ s390x_init(int when)
> machdep->process_elf_notes = s390x_process_elf_notes;
> break;
> case PRE_SYMTAB:
> + machdep->machspec = &s390x_machine_specific;
> machdep->verify_symbol = s390x_verify_symbol;
> if (pc->flags & KERNEL_DEBUG_QUERY)
> return;
> @@ -587,6 +787,8 @@ s390x_init(int when)
> machdep->kvbase = 0;
> machdep->identity_map_base = 0;
> machdep->is_kvaddr = generic_is_kvaddr;
> + if (!s390x_init_vm())
> + error(FATAL, "cannot initialize VM parameters.");
> machdep->is_uvaddr = s390x_is_uvaddr;
> machdep->eframe_search = s390x_eframe_search;
> machdep->back_trace = s390x_back_trace_cmd;
> @@ -681,7 +883,9 @@ s390x_dump_machdep_table(ulong arg)
> fprintf(fp, " dis_filter: s390x_dis_filter()\n");
> fprintf(fp, " cmd_mach: s390x_cmd_mach()\n");
> fprintf(fp, " get_smp_cpus: s390x_get_smp_cpus()\n");
> - fprintf(fp, " is_kvaddr: generic_is_kvaddr()\n");
> + fprintf(fp, " is_kvaddr: %s()\n", machdep->is_kvaddr ==
s390x_vr_is_kvaddr ?
> + "s390x_vr_is_kvaddr" :
> + "generic_is_kvaddr");
> fprintf(fp, " is_uvaddr: s390x_is_uvaddr()\n");
> fprintf(fp, " verify_paddr: generic_verify_paddr()\n");
> fprintf(fp, " get_kvaddr_ranges: s390x_get_kvaddr_ranges()\n");
> @@ -702,6 +906,12 @@ s390x_dump_machdep_table(ulong arg)
> fprintf(fp, " machspec: %lx\n",
(ulong)machdep->machspec);
> }
>
> +static int
> +s390x_vr_is_kvaddr(ulong vaddr)
> +{
> + return (vaddr < LOWCORE_SIZE) || (vaddr >= machdep->identity_map_base);
> +}
> +
> /*
> * Check if address is in context's address space
> */