Skip to content

Commit 57445f7

Browse files
committed
Merge: Enable virtio-mem on s390x
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/540 JIRA: https://issues.redhat.com/browse/RHEL-72992 Enable virtio-mem on s390x. Sanity tested with a self-built QEMU in the host, and then checking in the guest that the amount of memory changes in the guest in /proc/meminfo when adding or removing memory. Signed-off-by: Thomas Huth <thuth@redhat.com> Approved-by: Vitaly Kuznetsov <vkuznets@redhat.com> Approved-by: Philipp Rudo <prudo@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 6af2fcd + 939bac6 commit 57445f7

File tree

19 files changed

+511
-111
lines changed

19 files changed

+511
-111
lines changed

Documentation/virt/kvm/s390/s390-diag.rst

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,24 @@ DIAGNOSE function codes not specific to KVM, please refer to the
3535
documentation for the s390 hypervisors defining them.
3636

3737

38-
DIAGNOSE function code 'X'500' - KVM virtio functions
39-
-----------------------------------------------------
38+
DIAGNOSE function code 'X'500' - KVM functions
39+
----------------------------------------------
4040

41-
If the function code specifies 0x500, various virtio-related functions
42-
are performed.
41+
If the function code specifies 0x500, various KVM-specific functions
42+
are performed, including virtio functions.
4343

44-
General register 1 contains the virtio subfunction code. Supported
45-
virtio subfunctions depend on KVM's userspace. Generally, userspace
46-
provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
44+
General register 1 contains the subfunction code. Supported subfunctions
45+
depend on KVM's userspace. Regarding virtio subfunctions, generally
46+
userspace provides either s390-virtio (subcodes 0-2) or virtio-ccw
47+
(subcode 3).
4748

4849
Upon completion of the DIAGNOSE instruction, general register 2 contains
4950
the function's return code, which is either a return code or a subcode
5051
specific value.
5152

53+
If the specified subfunction is not supported, a SPECIFICATION exception
54+
will be triggered.
55+
5256
Subcode 0 - s390-virtio notification and early console printk
5357
Handled by userspace.
5458

@@ -76,6 +80,23 @@ Subcode 3 - virtio-ccw notification
7680

7781
See also the virtio standard for a discussion of this hypercall.
7882

83+
Subcode 4 - storage-limit
84+
Handled by userspace.
85+
86+
After completion of the DIAGNOSE call, general register 2 will
87+
contain the storage limit: the maximum physical address that might be
88+
used for storage throughout the lifetime of the VM.
89+
90+
The storage limit does not indicate currently usable storage, it may
91+
include holes, standby storage and areas reserved for other means, such
92+
as memory hotplug or virtio-mem devices. Other interfaces for detecting
93+
actually usable storage, such as SCLP, must be used in conjunction with
94+
this subfunction.
95+
96+
Note that the storage limit can be larger, but never smaller than the
97+
maximum storage address indicated by SCLP via the "maximum storage
98+
increment" and the "increment size".
99+
79100

80101
DIAGNOSE function code 'X'501 - KVM breakpoint
81102
----------------------------------------------

arch/s390/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ config S390
239239
select MODULES_USE_ELF_RELA
240240
select NEED_DMA_MAP_STATE if PCI
241241
select NEED_PER_CPU_EMBED_FIRST_CHUNK
242+
select NEED_PROC_VMCORE_DEVICE_RAM if PROC_VMCORE
242243
select NEED_SG_DMA_LENGTH if PCI
243244
select OLD_SIGACTION
244245
select OLD_SIGSUSPEND3

arch/s390/boot/physmem_info.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,42 @@ static int diag260(void)
112112
return 0;
113113
}
114114

115+
#define DIAG500_SC_STOR_LIMIT 4
116+
117+
static int diag500_storage_limit(unsigned long *max_physmem_end)
118+
{
119+
unsigned long storage_limit;
120+
unsigned long reg1, reg2;
121+
psw_t old;
122+
123+
asm volatile(
124+
" mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
125+
" epsw %[reg1],%[reg2]\n"
126+
" st %[reg1],0(%[psw_pgm])\n"
127+
" st %[reg2],4(%[psw_pgm])\n"
128+
" larl %[reg1],1f\n"
129+
" stg %[reg1],8(%[psw_pgm])\n"
130+
" lghi 1,%[subcode]\n"
131+
" lghi 2,0\n"
132+
" diag 2,4,0x500\n"
133+
"1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
134+
" lgr %[slimit],2\n"
135+
: [reg1] "=&d" (reg1),
136+
[reg2] "=&a" (reg2),
137+
[slimit] "=d" (storage_limit),
138+
"=Q" (get_lowcore()->program_new_psw),
139+
"=Q" (old)
140+
: [psw_old] "a" (&old),
141+
[psw_pgm] "a" (&get_lowcore()->program_new_psw),
142+
[subcode] "i" (DIAG500_SC_STOR_LIMIT)
143+
: "memory", "1", "2");
144+
if (!storage_limit)
145+
return -EINVAL;
146+
/* Convert inclusive end to exclusive end */
147+
*max_physmem_end = storage_limit + 1;
148+
return 0;
149+
}
150+
115151
static int tprot(unsigned long addr)
116152
{
117153
unsigned long reg1, reg2;
@@ -163,7 +199,9 @@ unsigned long detect_max_physmem_end(void)
163199
{
164200
unsigned long max_physmem_end = 0;
165201

166-
if (!sclp_early_get_memsize(&max_physmem_end)) {
202+
if (!diag500_storage_limit(&max_physmem_end)) {
203+
physmem_info.info_source = MEM_DETECT_DIAG500_STOR_LIMIT;
204+
} else if (!sclp_early_get_memsize(&max_physmem_end)) {
167205
physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO;
168206
} else {
169207
max_physmem_end = search_mem_end();
@@ -176,6 +214,13 @@ void detect_physmem_online_ranges(unsigned long max_physmem_end)
176214
{
177215
if (!sclp_early_read_storage_info()) {
178216
physmem_info.info_source = MEM_DETECT_SCLP_STOR_INFO;
217+
} else if (physmem_info.info_source == MEM_DETECT_DIAG500_STOR_LIMIT) {
218+
unsigned long online_end;
219+
220+
if (!sclp_early_get_memsize(&online_end)) {
221+
physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO;
222+
add_physmem_online_range(0, online_end);
223+
}
179224
} else if (!diag260()) {
180225
physmem_info.info_source = MEM_DETECT_DIAG260;
181226
} else if (max_physmem_end) {

arch/s390/boot/startup.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,15 @@ static void kaslr_adjust_got(unsigned long offset)
182182
* Merge information from several sources into a single ident_map_size value.
183183
* "ident_map_size" represents the upper limit of physical memory we may ever
184184
* reach. It might not be all online memory, but also include standby (offline)
185-
* memory. "ident_map_size" could be lower then actual standby or even online
185+
* memory or memory areas reserved for other means (e.g., memory devices such as
186+
* virtio-mem).
187+
*
188+
* "ident_map_size" could be lower then actual standby/reserved or even online
186189
* memory present, due to limiting factors. We should never go above this limit.
187190
* It is the size of our identity mapping.
188191
*
189192
* Consider the following factors:
190-
* 1. max_physmem_end - end of physical memory online or standby.
193+
* 1. max_physmem_end - end of physical memory online, standby or reserved.
191194
* Always >= end of the last online memory range (get_physmem_online_end()).
192195
* 2. CONFIG_MAX_PHYSMEM_BITS - the maximum size of physical memory the
193196
* kernel is able to support.

arch/s390/include/asm/physmem_info.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum physmem_info_source {
99
MEM_DETECT_NONE = 0,
1010
MEM_DETECT_SCLP_STOR_INFO,
1111
MEM_DETECT_DIAG260,
12+
MEM_DETECT_DIAG500_STOR_LIMIT,
1213
MEM_DETECT_SCLP_READ_INFO,
1314
MEM_DETECT_BIN_SEARCH
1415
};
@@ -107,6 +108,8 @@ static inline const char *get_physmem_info_source(void)
107108
return "sclp storage info";
108109
case MEM_DETECT_DIAG260:
109110
return "diag260";
111+
case MEM_DETECT_DIAG500_STOR_LIMIT:
112+
return "diag500 storage limit";
110113
case MEM_DETECT_SCLP_READ_INFO:
111114
return "sclp read info";
112115
case MEM_DETECT_BIN_SEARCH:

arch/s390/include/asm/sparsemem.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
#ifndef _ASM_S390_SPARSEMEM_H
33
#define _ASM_S390_SPARSEMEM_H
44

5-
#define SECTION_SIZE_BITS 28
5+
#define SECTION_SIZE_BITS 27
66
#define MAX_PHYSMEM_BITS CONFIG_MAX_PHYSMEM_BITS
77

8+
#ifdef CONFIG_NUMA
9+
static inline int memory_add_physaddr_to_nid(u64 addr)
10+
{
11+
return 0;
12+
}
13+
#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
14+
#endif /* CONFIG_NUMA */
15+
816
#endif /* _ASM_S390_SPARSEMEM_H */

arch/s390/kernel/crash_dump.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,19 @@ static int get_mem_chunk_cnt(void)
497497
return cnt;
498498
}
499499

500+
static void fill_ptload(Elf64_Phdr *phdr, unsigned long paddr,
501+
unsigned long vaddr, unsigned long size)
502+
{
503+
phdr->p_type = PT_LOAD;
504+
phdr->p_vaddr = vaddr;
505+
phdr->p_offset = paddr;
506+
phdr->p_paddr = paddr;
507+
phdr->p_filesz = size;
508+
phdr->p_memsz = size;
509+
phdr->p_flags = PF_R | PF_W | PF_X;
510+
phdr->p_align = PAGE_SIZE;
511+
}
512+
500513
/*
501514
* Initialize ELF loads (new kernel)
502515
*/
@@ -509,14 +522,8 @@ static void loads_init(Elf64_Phdr *phdr, bool os_info_has_vm)
509522
if (os_info_has_vm)
510523
old_identity_base = os_info_old_value(OS_INFO_IDENTITY_BASE);
511524
for_each_physmem_range(idx, &oldmem_type, &start, &end) {
512-
phdr->p_type = PT_LOAD;
513-
phdr->p_vaddr = old_identity_base + start;
514-
phdr->p_offset = start;
515-
phdr->p_paddr = start;
516-
phdr->p_filesz = end - start;
517-
phdr->p_memsz = end - start;
518-
phdr->p_flags = PF_R | PF_W | PF_X;
519-
phdr->p_align = PAGE_SIZE;
525+
fill_ptload(phdr, start, old_identity_base + start,
526+
end - start);
520527
phdr++;
521528
}
522529
}
@@ -526,6 +533,22 @@ static bool os_info_has_vm(void)
526533
return os_info_old_value(OS_INFO_KASLR_OFFSET);
527534
}
528535

536+
#ifdef CONFIG_PROC_VMCORE_DEVICE_RAM
537+
/*
538+
* Fill PT_LOAD for a physical memory range owned by a device and detected by
539+
* its device driver.
540+
*/
541+
void elfcorehdr_fill_device_ram_ptload_elf64(Elf64_Phdr *phdr,
542+
unsigned long long paddr, unsigned long long size)
543+
{
544+
unsigned long old_identity_base = 0;
545+
546+
if (os_info_has_vm())
547+
old_identity_base = os_info_old_value(OS_INFO_IDENTITY_BASE);
548+
fill_ptload(phdr, paddr, old_identity_base + paddr, size);
549+
}
550+
#endif
551+
529552
/*
530553
* Prepare PT_LOAD type program header for kernel image region
531554
*/

drivers/virtio/Kconfig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ config VIRTIO_BALLOON
122122

123123
config VIRTIO_MEM
124124
tristate "Virtio mem driver"
125-
depends on X86_64 || ARM64 || RISCV
125+
depends on X86_64 || ARM64 || RISCV || S390
126126
depends on VIRTIO
127127
depends on MEMORY_HOTPLUG
128128
depends on MEMORY_HOTREMOVE
@@ -132,11 +132,11 @@ config VIRTIO_MEM
132132
This driver provides access to virtio-mem paravirtualized memory
133133
devices, allowing to hotplug and hotunplug memory.
134134

135-
This driver currently only supports x86-64 and arm64. Although it
136-
should compile on other architectures that implement memory
137-
hot(un)plug, architecture-specific and/or common
138-
code changes may be required for virtio-mem, kdump and kexec to work as
139-
expected.
135+
This driver currently supports x86-64, arm64, riscv and s390.
136+
Although it should compile on other architectures that implement
137+
memory hot(un)plug, architecture-specific and/or common
138+
code changes may be required for virtio-mem, kdump and kexec to
139+
work as expected.
140140

141141
If unsure, say M.
142142

0 commit comments

Comments
 (0)