github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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  	switch hcrange {
   100  	case 1:
   101  		offset = 0xf000
   102  		maxhc = 0xf810
   103  	case 2:
   104  		offset = 0xef00
   105  		maxhc = 0xef20
   106  	}
   107  	hc := gen.r.Intn((maxhc-offset)/4)*4 + offset
   108  	gen.byte(imap.ld64(3, uint64(hc)))
   109  	for i := 4; i < n+4; i++ {
   110  		gen.byte(imap.ld64(uint(i), gen.r.Uint64()))
   111  	}
   112  	gen.byte(imap.sc(lev))
   113  }
   114  
   115  func (gen *generator) rtas() {
   116  	imap := gen.imap
   117  
   118  	addr := iset.GenerateInt(gen.cfg, gen.r, 8)
   119  	token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian.
   120  	reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4))
   121  
   122  	gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token))
   123  	for i := 0; i < gen.r.Intn(4)+1; i++ {
   124  		gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4),
   125  			uint32(iset.GenerateInt(gen.cfg, gen.r, 4))))
   126  	}
   127  	gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall
   128  	gen.byte(imap.ld64(4, addr))
   129  
   130  	gen.byte(imap.sc(1))
   131  }
   132  
   133  func (gen *generator) rfid() {
   134  	imap := gen.imap
   135  	tmpreg := uint(gen.r.Intn(32))
   136  
   137  	// SRR0 contains a PC
   138  	gen.byte(imap.ld64(tmpreg, iset.GenerateInt(gen.cfg, gen.r, 8)))
   139  	gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr0}))
   140  
   141  	// SRR1 contains an MSR
   142  	gen.byte(imap.ld64(tmpreg, gen.r.Uint64()))
   143  	gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr1}))
   144  
   145  	gen.byte(imap["rfid"].enc(map[string]uint{}))
   146  }