github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/ifuzz/powerpc/pseudo.go (about)

     1  // Copyright 2020 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package powerpc
     5  
     6  import (
     7  	"math/rand"
     8  
     9  	"github.com/google/syzkaller/pkg/ifuzz/iset"
    10  )
    11  
    12  const (
    13  	// Valid hcall humbers at the momemt are: 4..0x450.
    14  	MaxHcall = 0x450 // MAX_HCALL
    15  	SprnSrr0 = 0x01A // pc for rfid (SPRN_SRR0)
    16  	SprnSrr1 = 0x01B // msr for rfid (SPRN_SRR1)
    17  )
    18  
    19  // nolint:dupl
    20  func (insnset *InsnSet) initPseudo() {
    21  	insnset.Insns = append(insnset.Insns, &Insn{
    22  		Name:   "PSEUDO_hypercall",
    23  		Priv:   true,
    24  		Pseudo: true,
    25  		generator: func(cfg *iset.Config, r *rand.Rand) []byte {
    26  			gen := makeGen(insnset, cfg, r)
    27  			gen.sc(1)
    28  			return gen.text
    29  		},
    30  	})
    31  	insnset.Insns = append(insnset.Insns, &Insn{
    32  		Name:   "PSEUDO_syscall",
    33  		Priv:   true,
    34  		Pseudo: true,
    35  		generator: func(cfg *iset.Config, r *rand.Rand) []byte {
    36  			gen := makeGen(insnset, cfg, r)
    37  			gen.sc(0)
    38  			return gen.text
    39  		},
    40  	})
    41  	insnset.Insns = append(insnset.Insns, &Insn{
    42  		Name:   "PSEUDO_ultracall",
    43  		Priv:   true,
    44  		Pseudo: true,
    45  		generator: func(cfg *iset.Config, r *rand.Rand) []byte {
    46  			gen := makeGen(insnset, cfg, r)
    47  			gen.sc(2)
    48  			return gen.text
    49  		},
    50  	})
    51  	insnset.Insns = append(insnset.Insns, &Insn{
    52  		Name:   "PSEUDO_rtas",
    53  		Priv:   true,
    54  		Pseudo: true,
    55  		generator: func(cfg *iset.Config, r *rand.Rand) []byte {
    56  			gen := makeGen(insnset, cfg, r)
    57  			gen.rtas()
    58  			return gen.text
    59  		},
    60  	})
    61  	insnset.Insns = append(insnset.Insns, &Insn{
    62  		Name:   "PSEUDO_rfid",
    63  		Priv:   true,
    64  		Pseudo: true,
    65  		generator: func(cfg *iset.Config, r *rand.Rand) []byte {
    66  			gen := makeGen(insnset, cfg, r)
    67  			gen.rfid()
    68  			return gen.text
    69  		},
    70  	})
    71  }
    72  
    73  type generator struct {
    74  	imap insnSetMap
    75  	cfg  *iset.Config
    76  	r    *rand.Rand
    77  	text []byte
    78  }
    79  
    80  func makeGen(insnset *InsnSet, cfg *iset.Config, r *rand.Rand) *generator {
    81  	return &generator{
    82  		imap: insnset.insnMap,
    83  		cfg:  cfg,
    84  		r:    r,
    85  	}
    86  }
    87  
    88  func (gen *generator) byte(v []byte) {
    89  	gen.text = append(gen.text, v...)
    90  }
    91  
    92  func (gen *generator) sc(lev uint) {
    93  	imap := gen.imap
    94  
    95  	n := gen.r.Intn(9)
    96  	hcrange := gen.r.Intn(3)
    97  	offset := 4
    98  	maxhc := MaxHcall
    99  	if hcrange == 1 {
   100  		offset = 0xf000
   101  		maxhc = 0xf810
   102  	} else if hcrange == 2 {
   103  		offset = 0xef00
   104  		maxhc = 0xef20
   105  	}
   106  	hc := gen.r.Intn((maxhc-offset)/4)*4 + offset
   107  	gen.byte(imap.ld64(3, uint64(hc)))
   108  	for i := 4; i < n+4; i++ {
   109  		gen.byte(imap.ld64(uint(i), gen.r.Uint64()))
   110  	}
   111  	gen.byte(imap.sc(lev))
   112  }
   113  
   114  func (gen *generator) rtas() {
   115  	imap := gen.imap
   116  
   117  	addr := iset.GenerateInt(gen.cfg, gen.r, 8)
   118  	token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian.
   119  	reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4))
   120  
   121  	gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token))
   122  	for i := 0; i < gen.r.Intn(4)+1; i++ {
   123  		gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4),
   124  			uint32(iset.GenerateInt(gen.cfg, gen.r, 4))))
   125  	}
   126  	gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall
   127  	gen.byte(imap.ld64(4, addr))
   128  
   129  	gen.byte(imap.sc(1))
   130  }
   131  
   132  func (gen *generator) rfid() {
   133  	imap := gen.imap
   134  	tmpreg := uint(gen.r.Intn(32))
   135  
   136  	// SRR0 contains a PC
   137  	gen.byte(imap.ld64(tmpreg, iset.GenerateInt(gen.cfg, gen.r, 8)))
   138  	gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr0}))
   139  
   140  	// SRR1 contains an MSR
   141  	gen.byte(imap.ld64(tmpreg, gen.r.Uint64()))
   142  	gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr1}))
   143  
   144  	gen.byte(imap["rfid"].enc(map[string]uint{}))
   145  }