Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
Merge tag 's390-6.8-1' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/s390/linux

Pull s390 updates from Alexander Gordeev:

 - Add machine variable capacity information to /proc/sysinfo.

 - Limit the waste of page tables and always align vmalloc area size and
   base address on segment boundary.

 - Fix a memory leak when an attempt to register interruption sub class
   (ISC) for the adjunct-processor (AP) guest failed.

 - Reset response code AP_RESPONSE_INVALID_GISA to understandable by
   guest AP_RESPONSE_INVALID_ADDRESS in response to a failed
   interruption sub class (ISC) registration attempt.

 - Improve reaction to adjunct-processor (AP)
   AP_RESPONSE_OTHERWISE_CHANGED response code when enabling interrupts
   on behalf of a guest.

 - Fix incorrect sysfs 'status' attribute of adjunct-processor (AP)
   queue device bound to the vfio_ap device driver when the mediated
   device is attached to a guest, but the queue device is not passed
   through.

 - Rework struct ap_card to hold the whole adjunct-processor (AP) card
   hardware information. As result, all the ugly bit checks are replaced
   by simple evaluations of the required bit fields.

 - Improve handling of some weird scenarios between service element (SE)
   host and SE guest with adjunct-processor (AP) pass-through support.

 - Change local_ctl_set_bit() and local_ctl_clear_bit() so they return
   the previous value of the to be changed control register. This is
   useful if a bit is only changed temporarily and the previous content
   needs to be restored.

 - The kernel starts with machine checks disabled and is expected to
   enable it once trap_init() is called. However the implementation
   allows machine checks early. Consistently enable it in trap_init()
   only.

 - local_mcck_disable() and local_mcck_enable() assume that machine
   checks are always enabled. Instead implement and use
   local_mcck_save() and local_mcck_restore() to disable machine checks
   and restore the previous state.

 - Modification of floating point control (FPC) register of a traced
   process using ptrace interface may lead to corruption of the FPC
   register of the tracing process. Fix this.

 - kvm_arch_vcpu_ioctl_set_fpu() allows to set the floating point
   control (FPC) register in vCPU, but may lead to corruption of the FPC
   register of the host process. Fix this.

 - Use READ_ONCE() to read a vCPU floating point register value from the
   memory mapped area. This avoids that, depending on code generation, a
   different value is tested for validity than the one that is used.

 - Get rid of test_fp_ctl(), since it is quite subtle to use it
   correctly. Instead copy a new floating point control register value
   into its save area and test the validity of the new value when
   loading it.

 - Remove superfluous save_fpu_regs() call.

 - Remove s390 support for ARCH_WANTS_DYNAMIC_TASK_STRUCT. All machines
   provide the vector facility since many years and the need to make the
   task structure size dependent on the vector facility does not exist.

 - Remove the "novx" kernel command line option, as the vector code runs
   without any problems since many years.

 - Add the vector facility to the z13 architecture level set (ALS). All
   hypervisors support the vector facility since many years. This allows
   compile time optimizations of the kernel.

 - Get rid of MACHINE_HAS_VX and replace it with cpu_has_vx(). As
   result, the compiled code will have less runtime checks and less
   code.

 - Convert pgste_get_lock() and pgste_set_unlock() ASM inlines to C.

 - Convert the struct subchannel spinlock from pointer to member.

* tag 's390-6.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (24 commits)
  Revert "s390: update defconfigs"
  s390/cio: make sch->lock spinlock pointer a member
  s390: update defconfigs
  s390/mm: convert pgste locking functions to C
  s390/fpu: get rid of MACHINE_HAS_VX
  s390/als: add vector facility to z13 architecture level set
  s390/fpu: remove "novx" option
  s390/fpu: remove ARCH_WANTS_DYNAMIC_TASK_STRUCT support
  KVM: s390: remove superfluous save_fpu_regs() call
  s390/fpu: get rid of test_fp_ctl()
  KVM: s390: use READ_ONCE() to read fpc register value
  KVM: s390: fix setting of fpc register
  s390/ptrace: handle setting of fpc register correctly
  s390/nmi: implement and use local_mcck_save() / local_mcck_restore()
  s390/nmi: consistently enable machine checks in trap_init()
  s390/ctlreg: return old register contents when changing bits
  s390/ap: handle outband SE bind state change
  s390/ap: store TAPQ hwinfo in struct ap_card
  s390/vfio-ap: fix sysfs status attribute for AP queue devices
  s390/vfio-ap: improve reaction to response code 07 from PQAP(AQIC) command
  ...
  • Loading branch information
torvalds committed Jan 11, 2024
2 parents c299010 + b2b97a6 commit de927f6
Show file tree
Hide file tree
Showing 50 changed files with 518 additions and 456 deletions.
1 change: 0 additions & 1 deletion arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ config S390
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_SYM_ANNOTATIONS
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_WANTS_NO_INSTR
select ARCH_WANT_DEFAULT_BPF_JIT
select ARCH_WANT_IPC_PARSE_VERSION
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/boot/ipl_parm.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ void parse_boot_command_line(void)
memory_limit = round_down(memparse(val, NULL), PAGE_SIZE);

if (!strcmp(param, "vmalloc") && val) {
vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE);
vmalloc_size = round_up(memparse(val, NULL), _SEGMENT_SIZE);
vmalloc_size_set = 1;
}

Expand Down
3 changes: 2 additions & 1 deletion arch/s390/boot/startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ static unsigned long setup_kernel_memory_layout(void)
VMALLOC_END = MODULES_VADDR;

/* allow vmalloc area to occupy up to about 1/2 of the rest virtual space left */
vmalloc_size = min(vmalloc_size, round_down(VMALLOC_END / 2, _REGION3_SIZE));
vsize = round_down(VMALLOC_END / 2, _SEGMENT_SIZE);
vmalloc_size = min(vmalloc_size, vsize);
VMALLOC_START = VMALLOC_END - vmalloc_size;

/* split remaining virtual space between 1:1 mapping & vmemmap array */
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/crypto/chacha-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src,
* it cannot handle a block of data or less, but otherwise
* it can handle data of arbitrary size
*/
if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20 || !MACHINE_HAS_VX)
if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20 || !cpu_has_vx())
chacha_crypt_generic(state, dst, src, bytes, nrounds);
else
chacha20_crypt_s390(state, dst, src, bytes,
Expand Down
21 changes: 12 additions & 9 deletions arch/s390/include/asm/ap.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,21 @@ static inline bool ap_instructions_available(void)
}

/* TAPQ register GR2 response struct */
struct ap_tapq_gr2 {
struct ap_tapq_hwinfo {
union {
unsigned long value;
struct {
unsigned int fac : 32; /* facility bits */
unsigned int apinfo : 32; /* ap type, ... */
};
struct {
unsigned int s : 1; /* APSC */
unsigned int m : 1; /* AP4KM */
unsigned int c : 1; /* AP4KC */
unsigned int mode : 3;
unsigned int n : 1; /* APXA */
unsigned int apsc : 1; /* APSC */
unsigned int mex4k : 1; /* AP4KM */
unsigned int crt4k : 1; /* AP4KC */
unsigned int cca : 1; /* D */
unsigned int accel : 1; /* A */
unsigned int ep11 : 1; /* X */
unsigned int apxa : 1; /* APXA */
unsigned int : 1;
unsigned int class : 8;
unsigned int bs : 2; /* SE bind/assoc */
Expand All @@ -126,11 +128,12 @@ struct ap_tapq_gr2 {
/**
* ap_tapq(): Test adjunct processor queue.
* @qid: The AP queue number
* @info: Pointer to queue descriptor
* @info: Pointer to tapq hwinfo struct
*
* Returns AP queue status structure.
*/
static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *info)
static inline struct ap_queue_status ap_tapq(ap_qid_t qid,
struct ap_tapq_hwinfo *info)
{
union ap_queue_status_reg reg1;
unsigned long reg2;
Expand Down Expand Up @@ -158,7 +161,7 @@ static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *i
* Returns AP queue status structure.
*/
static inline struct ap_queue_status ap_test_queue(ap_qid_t qid, int tbit,
struct ap_tapq_gr2 *info)
struct ap_tapq_hwinfo *info)
{
if (tbit)
qid |= 1UL << 23; /* set T bit*/
Expand Down
24 changes: 14 additions & 10 deletions arch/s390/include/asm/ctlreg.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,22 +141,26 @@ static __always_inline void local_ctl_store(unsigned int cr, struct ctlreg *reg)
: [cr] "i" (cr));
}

static __always_inline void local_ctl_set_bit(unsigned int cr, unsigned int bit)
static __always_inline struct ctlreg local_ctl_set_bit(unsigned int cr, unsigned int bit)
{
struct ctlreg reg;
struct ctlreg new, old;

local_ctl_store(cr, &reg);
reg.val |= 1UL << bit;
local_ctl_load(cr, &reg);
local_ctl_store(cr, &old);
new = old;
new.val |= 1UL << bit;
local_ctl_load(cr, &new);
return old;
}

static __always_inline void local_ctl_clear_bit(unsigned int cr, unsigned int bit)
static __always_inline struct ctlreg local_ctl_clear_bit(unsigned int cr, unsigned int bit)
{
struct ctlreg reg;
struct ctlreg new, old;

local_ctl_store(cr, &reg);
reg.val &= ~(1UL << bit);
local_ctl_load(cr, &reg);
local_ctl_store(cr, &old);
new = old;
new.val &= ~(1UL << bit);
local_ctl_load(cr, &new);
return old;
}

struct lowcore;
Expand Down
35 changes: 21 additions & 14 deletions arch/s390/include/asm/fpu/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,33 @@

#include <linux/preempt.h>
#include <asm/asm-extable.h>
#include <asm/fpu/internal.h>

void save_fpu_regs(void);
void load_fpu_regs(void);
void __load_fpu_regs(void);

static inline int test_fp_ctl(u32 fpc)
/**
* sfpc_safe - Set floating point control register safely.
* @fpc: new value for floating point control register
*
* Set floating point control register. This may lead to an exception,
* since a saved value may have been modified by user space (ptrace,
* signal return, kvm registers) to an invalid value. In such a case
* set the floating point control register to zero.
*/
static inline void sfpc_safe(u32 fpc)
{
u32 orig_fpc;
int rc;

asm volatile(
" efpc %1\n"
" sfpc %2\n"
"0: sfpc %1\n"
" la %0,0\n"
"1:\n"
EX_TABLE(0b,1b)
: "=d" (rc), "=&d" (orig_fpc)
: "d" (fpc), "0" (-EINVAL));
return rc;
asm volatile("\n"
"0: sfpc %[fpc]\n"
"1: nopr %%r7\n"
".pushsection .fixup, \"ax\"\n"
"2: lghi %[fpc],0\n"
" jg 0b\n"
".popsection\n"
EX_TABLE(1b, 2b)
: [fpc] "+d" (fpc)
: : "memory");
}

#define KERNEL_FPC 1
Expand Down
10 changes: 8 additions & 2 deletions arch/s390/include/asm/fpu/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
#define _ASM_S390_FPU_INTERNAL_H

#include <linux/string.h>
#include <asm/facility.h>
#include <asm/fpu/types.h>

static inline bool cpu_has_vx(void)
{
return likely(test_facility(129));
}

static inline void save_vx_regs(__vector128 *vxrs)
{
asm volatile(
Expand Down Expand Up @@ -41,7 +47,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpregs->pad = 0;
fpregs->fpc = fpu->fpc;
if (MACHINE_HAS_VX)
if (cpu_has_vx())
convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
else
memcpy((freg_t *)&fpregs->fprs, fpu->fprs,
Expand All @@ -51,7 +57,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpu->fpc = fpregs->fpc;
if (MACHINE_HAS_VX)
if (cpu_has_vx())
convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
else
memcpy(fpu->fprs, (freg_t *)&fpregs->fprs,
Expand Down
34 changes: 26 additions & 8 deletions arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,7 @@ struct thread_struct {
struct gs_cb *gs_cb; /* Current guarded storage cb */
struct gs_cb *gs_bc_cb; /* Broadcast guarded storage cb */
struct pgm_tdb trap_tdb; /* Transaction abort diagnose block */
/*
* Warning: 'fpu' is dynamically-sized. It *MUST* be at
* the end.
*/
struct fpu fpu; /* FP and VX register save area */
struct fpu fpu; /* FP and VX register save area */
};

/* Flag to disable transactions. */
Expand Down Expand Up @@ -331,14 +327,36 @@ static inline unsigned long __extract_psw(void)
return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
}

static inline void local_mcck_enable(void)
static inline unsigned long __local_mcck_save(void)
{
__load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
unsigned long mask = __extract_psw();

__load_psw_mask(mask & ~PSW_MASK_MCHECK);
return mask & PSW_MASK_MCHECK;
}

#define local_mcck_save(mflags) \
do { \
typecheck(unsigned long, mflags); \
mflags = __local_mcck_save(); \
} while (0)

static inline void local_mcck_restore(unsigned long mflags)
{
unsigned long mask = __extract_psw();

mask &= ~PSW_MASK_MCHECK;
__load_psw_mask(mask | mflags);
}

static inline void local_mcck_disable(void)
{
__load_psw_mask(__extract_psw() & ~PSW_MASK_MCHECK);
__local_mcck_save();
}

static inline void local_mcck_enable(void)
{
__load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
}

/*
Expand Down
2 changes: 0 additions & 2 deletions arch/s390/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#define MACHINE_FLAG_TOPOLOGY BIT(10)
#define MACHINE_FLAG_TE BIT(11)
#define MACHINE_FLAG_TLB_LC BIT(12)
#define MACHINE_FLAG_VX BIT(13)
#define MACHINE_FLAG_TLB_GUEST BIT(14)
#define MACHINE_FLAG_NX BIT(15)
#define MACHINE_FLAG_GS BIT(16)
Expand Down Expand Up @@ -90,7 +89,6 @@ extern unsigned long mio_wb_bit_mask;
#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
#define MACHINE_HAS_TLB_GUEST (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_GUEST)
#define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX)
#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS)
Expand Down
4 changes: 4 additions & 0 deletions arch/s390/include/asm/sysinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ struct sysinfo_1_1_1 {
unsigned int ncr;
unsigned int npr;
unsigned int ntr;
char reserved_3[4];
char model_var_cap[16];
unsigned int model_var_cap_rating;
unsigned int nvr;
};

struct sysinfo_1_2_1 {
Expand Down
16 changes: 7 additions & 9 deletions arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <asm/lowcore.h>
#include <asm/switch_to.h>
#include <asm/vdso.h>
#include <asm/fpu/api.h>
#include "compat_linux.h"
#include "compat_ptrace.h"
#include "entry.h"
Expand Down Expand Up @@ -98,10 +99,6 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI))
return -EINVAL;

/* Test the floating-point-control word. */
if (test_fp_ctl(user_sregs.fpregs.fpc))
return -EINVAL;

/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
Expand Down Expand Up @@ -137,7 +134,7 @@ static int save_sigregs_ext32(struct pt_regs *regs,
return -EFAULT;

/* Save vector registers to signal stack */
if (MACHINE_HAS_VX) {
if (cpu_has_vx()) {
for (i = 0; i < __NUM_VXRS_LOW; i++)
vxrs[i] = current->thread.fpu.vxrs[i].low;
if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
Expand Down Expand Up @@ -165,7 +162,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
*(__u32 *)&regs->gprs[i] = gprs_high[i];

/* Restore vector registers from signal stack */
if (MACHINE_HAS_VX) {
if (cpu_has_vx()) {
if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
sizeof(sregs_ext->vxrs_low)) ||
__copy_from_user(current->thread.fpu.vxrs + __NUM_VXRS_LOW,
Expand Down Expand Up @@ -265,7 +262,7 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
* the machine supports it
*/
frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved);
if (!MACHINE_HAS_VX)
if (!cpu_has_vx())
frame_size -= sizeof(frame->sregs_ext.vxrs_low) +
sizeof(frame->sregs_ext.vxrs_high);
frame = get_sigframe(&ksig->ka, regs, frame_size);
Expand Down Expand Up @@ -348,11 +345,12 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
* the machine supports it
*/
uc_flags = UC_GPRS_HIGH;
if (MACHINE_HAS_VX) {
if (cpu_has_vx()) {
uc_flags |= UC_VXRS;
} else
} else {
frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
sizeof(frame->uc.uc_mcontext_ext.vxrs_high);
}
frame = get_sigframe(&ksig->ka, regs, frame_size);
if (frame == (void __user *) -1UL)
return -EFAULT;
Expand Down
5 changes: 3 additions & 2 deletions arch/s390/kernel/crash_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/ipl.h>
#include <asm/sclp.h>
#include <asm/maccess.h>
#include <asm/fpu/api.h>

#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
Expand Down Expand Up @@ -319,7 +320,7 @@ static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa)
ptr = nt_init(ptr, NT_S390_TODPREG, &sa->todpreg, sizeof(sa->todpreg));
ptr = nt_init(ptr, NT_S390_CTRS, &sa->ctrs, sizeof(sa->ctrs));
ptr = nt_init(ptr, NT_S390_PREFIX, &sa->prefix, sizeof(sa->prefix));
if (MACHINE_HAS_VX) {
if (cpu_has_vx()) {
ptr = nt_init(ptr, NT_S390_VXRS_HIGH,
&sa->vxrs_high, sizeof(sa->vxrs_high));
ptr = nt_init(ptr, NT_S390_VXRS_LOW,
Expand All @@ -343,7 +344,7 @@ static size_t get_cpu_elf_notes_size(void)
size += nt_size(NT_S390_TODPREG, sizeof(sa->todpreg));
size += nt_size(NT_S390_CTRS, sizeof(sa->ctrs));
size += nt_size(NT_S390_PREFIX, sizeof(sa->prefix));
if (MACHINE_HAS_VX) {
if (cpu_has_vx()) {
size += nt_size(NT_S390_VXRS_HIGH, sizeof(sa->vxrs_high));
size += nt_size(NT_S390_VXRS_LOW, sizeof(sa->vxrs_low));
}
Expand Down
12 changes: 1 addition & 11 deletions arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,8 @@ static __init void detect_machine_facilities(void)
}
if (test_facility(51))
S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
if (test_facility(129)) {
S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
if (test_facility(129))
system_ctl_set_bit(0, CR0_VECTOR_BIT);
}
if (test_facility(130))
S390_lowcore.machine_flags |= MACHINE_FLAG_NX;
if (test_facility(133))
Expand Down Expand Up @@ -271,14 +269,6 @@ static inline void setup_access_registers(void)
restore_access_regs(acrs);
}

static int __init disable_vector_extension(char *str)
{
S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
system_ctl_clear_bit(0, CR0_VECTOR_BIT);
return 0;
}
early_param("novx", disable_vector_extension);

char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
static void __init setup_boot_command_line(void)
{
Expand Down
Loading

0 comments on commit de927f6

Please sign in to comment.