Skip to content

Commit f15587c

Browse files
committed
Merge branch 'pvbase' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
s390 base parts (non kvm) for protvirt
2 parents 11a48a5 + a0f60f8 commit f15587c

File tree

15 files changed

+659
-14
lines changed

15 files changed

+659
-14
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,6 +3795,11 @@
37953795
before loading.
37963796
See Documentation/admin-guide/blockdev/ramdisk.rst.
37973797

3798+
prot_virt= [S390] enable hosting protected virtual machines
3799+
isolated from the hypervisor (if hardware supports
3800+
that).
3801+
Format: <bool>
3802+
37983803
psi= [KNL] Enable or disable pressure stall information
37993804
tracking.
38003805
Format: <bool>

arch/s390/boot/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
3737
obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
3838
obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
3939
obj-y += version.o pgm_check_info.o ctype.o text_dma.o
40-
obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o
40+
obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o
4141
obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o
4242
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
4343
targets := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)

arch/s390/boot/uv.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
#include <asm/facility.h>
44
#include <asm/sections.h>
55

6+
/* will be used in arch/s390/kernel/uv.c */
7+
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
68
int __bootdata_preserved(prot_virt_guest);
9+
#endif
10+
#if IS_ENABLED(CONFIG_KVM)
11+
struct uv_info __bootdata_preserved(uv_info);
12+
#endif
713

814
void uv_query_info(void)
915
{
@@ -19,7 +25,21 @@ void uv_query_info(void)
1925
if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != 0x100)
2026
return;
2127

28+
if (IS_ENABLED(CONFIG_KVM)) {
29+
memcpy(uv_info.inst_calls_list, uvcb.inst_calls_list, sizeof(uv_info.inst_calls_list));
30+
uv_info.uv_base_stor_len = uvcb.uv_base_stor_len;
31+
uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len;
32+
uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len;
33+
uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len;
34+
uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len;
35+
uv_info.max_sec_stor_addr = ALIGN(uvcb.max_guest_stor_addr, PAGE_SIZE);
36+
uv_info.max_num_sec_conf = uvcb.max_num_sec_conf;
37+
uv_info.max_guest_cpus = uvcb.max_guest_cpus;
38+
}
39+
40+
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
2241
if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) &&
2342
test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list))
2443
prot_virt_guest = 1;
44+
#endif
2545
}

arch/s390/include/asm/gmap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _ASM_S390_GMAP_H
1010
#define _ASM_S390_GMAP_H
1111

12+
#include <linux/radix-tree.h>
1213
#include <linux/refcount.h>
1314

1415
/* Generic bits for GMAP notification on DAT table entry changes. */
@@ -31,6 +32,7 @@
3132
* @table: pointer to the page directory
3233
* @asce: address space control element for gmap page table
3334
* @pfault_enabled: defines if pfaults are applicable for the guest
35+
* @guest_handle: protected virtual machine handle for the ultravisor
3436
* @host_to_rmap: radix tree with gmap_rmap lists
3537
* @children: list of shadow gmap structures
3638
* @pt_list: list of all page tables used in the shadow guest address space
@@ -54,6 +56,8 @@ struct gmap {
5456
unsigned long asce_end;
5557
void *private;
5658
bool pfault_enabled;
59+
/* only set for protected virtual machines */
60+
unsigned long guest_handle;
5761
/* Additional data for shadow guest address spaces */
5862
struct radix_tree_root host_to_rmap;
5963
struct list_head children;

arch/s390/include/asm/mmu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ typedef struct {
1616
unsigned long asce;
1717
unsigned long asce_limit;
1818
unsigned long vdso_base;
19+
/* The mmu context belongs to a secure guest. */
20+
atomic_t is_protected;
1921
/*
2022
* The following bitfields need a down_write on the mm
2123
* semaphore when they are written to. As they are only

arch/s390/include/asm/mmu_context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static inline int init_new_context(struct task_struct *tsk,
2323
INIT_LIST_HEAD(&mm->context.gmap_list);
2424
cpumask_clear(&mm->context.cpu_attach_mask);
2525
atomic_set(&mm->context.flush_count, 0);
26+
atomic_set(&mm->context.is_protected, 0);
2627
mm->context.gmap_asce = 0;
2728
mm->context.flush_mm = 0;
2829
mm->context.compat_mm = test_thread_flag(TIF_31BIT);

arch/s390/include/asm/page.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ static inline int devmem_is_allowed(unsigned long pfn)
153153
#define HAVE_ARCH_FREE_PAGE
154154
#define HAVE_ARCH_ALLOC_PAGE
155155

156+
#if IS_ENABLED(CONFIG_PGSTE)
157+
int arch_make_page_accessible(struct page *page);
158+
#define HAVE_ARCH_MAKE_PAGE_ACCESSIBLE
159+
#endif
160+
156161
#endif /* !__ASSEMBLY__ */
157162

158163
#define __PAGE_OFFSET 0x0UL

arch/s390/include/asm/pgtable.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/atomic.h>
2020
#include <asm/bug.h>
2121
#include <asm/page.h>
22+
#include <asm/uv.h>
2223

2324
extern pgd_t swapper_pg_dir[];
2425
extern void paging_init(void);
@@ -520,6 +521,15 @@ static inline int mm_has_pgste(struct mm_struct *mm)
520521
return 0;
521522
}
522523

524+
static inline int mm_is_protected(struct mm_struct *mm)
525+
{
526+
#ifdef CONFIG_PGSTE
527+
if (unlikely(atomic_read(&mm->context.is_protected)))
528+
return 1;
529+
#endif
530+
return 0;
531+
}
532+
523533
static inline int mm_alloc_pgste(struct mm_struct *mm)
524534
{
525535
#ifdef CONFIG_PGSTE
@@ -1061,7 +1071,12 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
10611071
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
10621072
unsigned long addr, pte_t *ptep)
10631073
{
1064-
return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
1074+
pte_t res;
1075+
1076+
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
1077+
if (mm_is_protected(mm) && pte_present(res))
1078+
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1079+
return res;
10651080
}
10661081

10671082
#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
@@ -1073,7 +1088,12 @@ void ptep_modify_prot_commit(struct vm_area_struct *, unsigned long,
10731088
static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
10741089
unsigned long addr, pte_t *ptep)
10751090
{
1076-
return ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
1091+
pte_t res;
1092+
1093+
res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
1094+
if (mm_is_protected(vma->vm_mm) && pte_present(res))
1095+
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1096+
return res;
10771097
}
10781098

10791099
/*
@@ -1088,12 +1108,17 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
10881108
unsigned long addr,
10891109
pte_t *ptep, int full)
10901110
{
1111+
pte_t res;
1112+
10911113
if (full) {
1092-
pte_t pte = *ptep;
1114+
res = *ptep;
10931115
*ptep = __pte(_PAGE_INVALID);
1094-
return pte;
1116+
} else {
1117+
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
10951118
}
1096-
return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
1119+
if (mm_is_protected(mm) && pte_present(res))
1120+
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1121+
return res;
10971122
}
10981123

10991124
#define __HAVE_ARCH_PTEP_SET_WRPROTECT

arch/s390/include/asm/uv.h

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/errno.h>
1616
#include <linux/bug.h>
1717
#include <asm/page.h>
18+
#include <asm/gmap.h>
1819

1920
#define UVC_RC_EXECUTED 0x0001
2021
#define UVC_RC_INV_CMD 0x0002
@@ -23,14 +24,24 @@
2324
#define UVC_RC_NO_RESUME 0x0007
2425

2526
#define UVC_CMD_QUI 0x0001
27+
#define UVC_CMD_INIT_UV 0x000f
28+
#define UVC_CMD_CONV_TO_SEC_STOR 0x0200
29+
#define UVC_CMD_CONV_FROM_SEC_STOR 0x0201
30+
#define UVC_CMD_PIN_PAGE_SHARED 0x0341
31+
#define UVC_CMD_UNPIN_PAGE_SHARED 0x0342
2632
#define UVC_CMD_SET_SHARED_ACCESS 0x1000
2733
#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001
2834

2935
/* Bits in installed uv calls */
3036
enum uv_cmds_inst {
3137
BIT_UVC_CMD_QUI = 0,
38+
BIT_UVC_CMD_INIT_UV = 1,
39+
BIT_UVC_CMD_CONV_TO_SEC_STOR = 6,
40+
BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7,
3241
BIT_UVC_CMD_SET_SHARED_ACCESS = 8,
3342
BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9,
43+
BIT_UVC_CMD_PIN_PAGE_SHARED = 21,
44+
BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
3445
};
3546

3647
struct uv_cb_header {
@@ -44,7 +55,40 @@ struct uv_cb_qui {
4455
struct uv_cb_header header;
4556
u64 reserved08;
4657
u64 inst_calls_list[4];
47-
u64 reserved30[15];
58+
u64 reserved30[2];
59+
u64 uv_base_stor_len;
60+
u64 reserved48;
61+
u64 conf_base_phys_stor_len;
62+
u64 conf_base_virt_stor_len;
63+
u64 conf_virt_var_stor_len;
64+
u64 cpu_stor_len;
65+
u32 reserved70[3];
66+
u32 max_num_sec_conf;
67+
u64 max_guest_stor_addr;
68+
u8 reserved88[158 - 136];
69+
u16 max_guest_cpus;
70+
u8 reserveda0[200 - 160];
71+
} __packed __aligned(8);
72+
73+
struct uv_cb_init {
74+
struct uv_cb_header header;
75+
u64 reserved08[2];
76+
u64 stor_origin;
77+
u64 stor_len;
78+
u64 reserved28[4];
79+
} __packed __aligned(8);
80+
81+
struct uv_cb_cts {
82+
struct uv_cb_header header;
83+
u64 reserved08[2];
84+
u64 guest_handle;
85+
u64 gaddr;
86+
} __packed __aligned(8);
87+
88+
struct uv_cb_cfs {
89+
struct uv_cb_header header;
90+
u64 reserved08[2];
91+
u64 paddr;
4892
} __packed __aligned(8);
4993

5094
struct uv_cb_share {
@@ -69,6 +113,20 @@ static inline int uv_call(unsigned long r1, unsigned long r2)
69113
return cc;
70114
}
71115

116+
struct uv_info {
117+
unsigned long inst_calls_list[4];
118+
unsigned long uv_base_stor_len;
119+
unsigned long guest_base_stor_len;
120+
unsigned long guest_virt_base_stor_len;
121+
unsigned long guest_virt_var_stor_len;
122+
unsigned long guest_cpu_stor_len;
123+
unsigned long max_sec_stor_addr;
124+
unsigned int max_num_sec_conf;
125+
unsigned short max_guest_cpus;
126+
};
127+
128+
extern struct uv_info uv_info;
129+
72130
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
73131
extern int prot_virt_guest;
74132

@@ -121,11 +179,40 @@ static inline int uv_remove_shared(unsigned long addr)
121179
return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
122180
}
123181

124-
void uv_query_info(void);
125182
#else
126183
#define is_prot_virt_guest() 0
127184
static inline int uv_set_shared(unsigned long addr) { return 0; }
128185
static inline int uv_remove_shared(unsigned long addr) { return 0; }
186+
#endif
187+
188+
#if IS_ENABLED(CONFIG_KVM)
189+
extern int prot_virt_host;
190+
191+
static inline int is_prot_virt_host(void)
192+
{
193+
return prot_virt_host;
194+
}
195+
196+
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
197+
int uv_convert_from_secure(unsigned long paddr);
198+
int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
199+
200+
void setup_uv(void);
201+
void adjust_to_uv_max(unsigned long *vmax);
202+
#else
203+
#define is_prot_virt_host() 0
204+
static inline void setup_uv(void) {}
205+
static inline void adjust_to_uv_max(unsigned long *vmax) {}
206+
207+
static inline int uv_convert_from_secure(unsigned long paddr)
208+
{
209+
return 0;
210+
}
211+
#endif
212+
213+
#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
214+
void uv_query_info(void);
215+
#else
129216
static inline void uv_query_info(void) {}
130217
#endif
131218

arch/s390/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
7878
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_diag.o
7979

8080
obj-$(CONFIG_TRACEPOINTS) += trace.o
81+
obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o
8182

8283
# vdso
8384
obj-y += vdso64/

0 commit comments

Comments
 (0)