Skip to content

Commit

Permalink
KVM: s390: Decoding helper functions.
Browse files Browse the repository at this point in the history
Introduce helper functions for decoding the various base/displacement
instruction formats.

Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
  • Loading branch information
Cornelia Huck authored and Marcelo Tosatti committed Jan 7, 2013
1 parent 7797535 commit b1c571a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 51 deletions.
21 changes: 6 additions & 15 deletions arch/s390/kvm/intercept.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,22 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
{
int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
((vcpu->arch.sie_block->ipb & 0xff00) << 4);
u64 useraddr;
int reg, rc;

vcpu->stat.instruction_lctlg++;
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
return -EOPNOTSUPP;

useraddr = disp2;
if (base2)
useraddr += vcpu->run->s.regs.gprs[base2];
useraddr = kvm_s390_get_base_disp_rsy(vcpu);

if (useraddr & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);

reg = reg1;

VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
disp2);
VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
useraddr);
trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);

do {
Expand All @@ -68,23 +63,19 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
{
int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 useraddr;
u32 val = 0;
int reg, rc;

vcpu->stat.instruction_lctl++;

useraddr = disp2;
if (base2)
useraddr += vcpu->run->s.regs.gprs[base2];
useraddr = kvm_s390_get_base_disp_rs(vcpu);

if (useraddr & 3)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);

VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
disp2);
VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
useraddr);
trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);

reg = reg1;
Expand Down
37 changes: 37 additions & 0 deletions arch/s390/kvm/kvm-s390.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,43 @@ static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
vcpu->arch.sie_block->ihcpu = 0xffff;
}

static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);

return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}

static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
u64 *address1, u64 *address2)
{
int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;

*address1 = (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
*address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}

static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
((vcpu->arch.sie_block->ipb & 0xff00) << 4);

return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}

static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);

return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}

int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
void kvm_s390_tasklet(unsigned long parm);
Expand Down
42 changes: 11 additions & 31 deletions arch/s390/kvm/priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@

static int handle_set_prefix(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 operand2;
u32 address = 0;
u8 tmp;

vcpu->stat.instruction_spx++;

operand2 = disp2;
if (base2)
operand2 += vcpu->run->s.regs.gprs[base2];
operand2 = kvm_s390_get_base_disp_s(vcpu);

/* must be word boundary */
if (operand2 & 3) {
Expand Down Expand Up @@ -67,15 +63,12 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)

static int handle_store_prefix(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 operand2;
u32 address;

vcpu->stat.instruction_stpx++;
operand2 = disp2;
if (base2)
operand2 += vcpu->run->s.regs.gprs[base2];

operand2 = kvm_s390_get_base_disp_s(vcpu);

/* must be word boundary */
if (operand2 & 3) {
Expand All @@ -100,15 +93,12 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)

static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 useraddr;
int rc;

vcpu->stat.instruction_stap++;
useraddr = disp2;
if (base2)
useraddr += vcpu->run->s.regs.gprs[base2];

useraddr = kvm_s390_get_base_disp_s(vcpu);

if (useraddr & 1) {
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
Expand Down Expand Up @@ -178,15 +168,12 @@ static int handle_stfl(struct kvm_vcpu *vcpu)

static int handle_stidp(struct kvm_vcpu *vcpu)
{
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 operand2;
int rc;

vcpu->stat.instruction_stidp++;
operand2 = disp2;
if (base2)
operand2 += vcpu->run->s.regs.gprs[base2];

operand2 = kvm_s390_get_base_disp_s(vcpu);

if (operand2 & 7) {
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
Expand Down Expand Up @@ -240,17 +227,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff;
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u64 operand2;
unsigned long mem;

vcpu->stat.instruction_stsi++;
VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);

operand2 = disp2;
if (base2)
operand2 += vcpu->run->s.regs.gprs[base2];
operand2 = kvm_s390_get_base_disp_s(vcpu);

if (operand2 & 0xfff && fc > 0)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
Expand Down Expand Up @@ -335,17 +318,14 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)

static int handle_tprot(struct kvm_vcpu *vcpu)
{
int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
u64 address1 = disp1 + base1 ? vcpu->run->s.regs.gprs[base1] : 0;
u64 address2 = disp2 + base2 ? vcpu->run->s.regs.gprs[base2] : 0;
u64 address1, address2;
struct vm_area_struct *vma;
unsigned long user_address;

vcpu->stat.instruction_tprot++;

kvm_s390_get_base_disp_sse(vcpu, &address1, &address2);

/* we only handle the Linux memory detection case:
* access key == 0
* guest DAT == off
Expand Down
6 changes: 1 addition & 5 deletions arch/s390/kvm/sigp.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
{
int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
int r3 = vcpu->arch.sie_block->ipa & 0x000f;
int base2 = vcpu->arch.sie_block->ipb >> 28;
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
u32 parameter;
u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
u8 order_code;
Expand All @@ -336,9 +334,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
return kvm_s390_inject_program_int(vcpu,
PGM_PRIVILEGED_OPERATION);

order_code = disp2;
if (base2)
order_code += vcpu->run->s.regs.gprs[base2];
order_code = kvm_s390_get_base_disp_rs(vcpu);

if (r1 % 2)
parameter = vcpu->run->s.regs.gprs[r1];
Expand Down

0 comments on commit b1c571a

Please sign in to comment.